changeset 5138:4d8ebb0fc484

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 21 Mar 2012 13:57:30 +0100
parents 09f66048738e (current diff) 7b2efb5ff2ea (diff)
children ee615aee55b4
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotNoProfilingInfo.java
diffstat 72 files changed, 887 insertions(+), 464 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Mar 21 13:57:30 2012 +0100
@@ -26,10 +26,6 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.max.asm.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.cri.xir.*;
 import com.oracle.graal.alloc.simple.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
@@ -44,6 +40,10 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.max.asm.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.xir.*;
 
 public class GraalCompiler {
 
@@ -74,11 +74,7 @@
         this.backend = backend;
     }
 
-    public CiTargetMethod compileMethod(RiResolvedMethod method, int osrBCI, PhasePlan plan) {
-        return compileMethod(method, new StructuredGraph(method), osrBCI, plan);
-    }
-
-    public CiTargetMethod compileMethod(final RiResolvedMethod method, final StructuredGraph graph, int osrBCI, final PhasePlan plan) {
+    public CiTargetMethod compileMethod(final RiResolvedMethod method, final StructuredGraph graph, int osrBCI, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) {
         assert (method.accessFlags() & Modifier.NATIVE) == 0 : "compiling native methods is not supported";
         if (osrBCI != -1) {
             throw new CiBailout("No OSR supported");
@@ -89,7 +85,7 @@
                 final CiAssumptions assumptions = GraalOptions.OptAssumptions ? new CiAssumptions() : null;
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
                     public LIR call() {
-                        return emitHIR(graph, assumptions, plan);
+                        return emitHIR(graph, assumptions, plan, optimisticOpts);
                     }
                 });
                 final FrameMap frameMap = Debug.scope("BackEnd", lir, new Callable<FrameMap>() {
@@ -109,7 +105,7 @@
     /**
      * Builds the graph, optimizes it.
      */
-    public LIR emitHIR(StructuredGraph graph, CiAssumptions assumptions, PhasePlan plan) {
+    public LIR emitHIR(StructuredGraph graph, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
 
         if (graph.start().next() == null) {
             plan.runPhases(PhasePosition.AFTER_PARSING, graph);
@@ -141,7 +137,7 @@
         }
 
         if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) {
-            new InliningPhase(target, runtime, null, assumptions, plan).apply(graph);
+            new InliningPhase(target, runtime, null, assumptions, plan, optimisticOpts).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
             new PhiStampPhase().apply(graph);
         }
@@ -161,7 +157,7 @@
         }
 
         if (GraalOptions.EscapeAnalysis && !plan.isPhaseDisabled(EscapeAnalysisPhase.class)) {
-            new EscapeAnalysisPhase(target, runtime, assumptions, plan).apply(graph);
+            new EscapeAnalysisPhase(target, runtime, assumptions, plan, optimisticOpts).apply(graph);
             new PhiStampPhase().apply(graph);
             if (GraalOptions.OptCanonicalizer) {
                 new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Wed Mar 21 13:57:30 2012 +0100
@@ -44,9 +44,9 @@
     public static boolean Inline                             = true;
     public static boolean Intrinsify                         = true;
     public static boolean CacheGraphs                        = ____;
-    public static boolean InlineMonomorphicCalls             = true;
-    public static boolean InlinePolymorphicCalls             = true;
-    public static boolean InlineMegamorphicCalls             = ____;
+           static boolean InlineMonomorphicCalls             = true;
+           static boolean InlinePolymorphicCalls             = true;
+           static boolean InlineMegamorphicCalls             = ____;
     public static int     InliningPolicy                     = 4;
     public static int     WeightComputationPolicy            = 2;
     public static int     MaximumTrivialSize                 = 10;
@@ -81,6 +81,8 @@
     public static int     LoopFrequencyPropagationPolicy     = -2;
 
     // profiling information
+    public static int     DeoptsToDisableOptimisticOptimization = 40;
+    public static boolean PrintDisabledOptimisticOptimizations = true;
     public static int     MatureExecutionsBranch             = 1;
     public static int     MatureExecutionsPerSwitchCase      = 1;
     public static int     MatureExecutionsTypeProfile        = 1;
@@ -139,6 +141,7 @@
     public static int     TraceLIRGeneratorLevel             = 0;
     public static boolean TraceEscapeAnalysis                = ____;
     public static int     TraceBytecodeParserLevel           = 0;
+    public static boolean PrintBailouts                      = true;
     public static boolean ExitVMOnBailout                    = ____;
     public static boolean ExitVMOnException                  = true;
 
@@ -147,13 +150,14 @@
 
     // Code generator settings
     public static boolean PropagateTypes                     = ____;
-    public static boolean UseBranchPrediction                = true;
-    public static boolean UseExceptionProbability            = true;
+    public static boolean UseProfilingInformation            = true;
+           static boolean RemoveNeverExecutedCode            = true;
+           static boolean UseExceptionProbability            = true;
     public static boolean AllowExplicitExceptionChecks       = true;
     public static boolean OmitHotExceptionStacktrace         = ____;
     public static boolean GenSafepoints                      = true;
     public static boolean GenLoopSafepoints                  = true;
-    public static boolean UseTypeCheckHints                  = true;
+           static boolean UseTypeCheckHints                  = true;
     public static boolean InlineVTableStubs                  = ____;
     public static boolean AlwaysInlineVTableStubs            = ____;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/OptimisticOptimizations.java	Wed Mar 21 13:57:30 2012 +0100
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.criutils.*;
+
+
+
+public final class OptimisticOptimizations {
+    public static final OptimisticOptimizations ALL = new OptimisticOptimizations(EnumSet.allOf(Optimization.class));
+    public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class));
+    private static final DebugMetric disabledOptimisticOptsMetric = Debug.metric("DisabledOptimisticOpts");
+
+    private static enum Optimization {
+        RemoveNeverExecutedCode,
+        UseTypeCheckedInlining,
+        UseTypeCheckHints,
+        UseExceptionProbability
+    }
+
+    private final Set<Optimization> enabledOpts;
+
+    public OptimisticOptimizations(RiResolvedMethod method) {
+        this.enabledOpts = EnumSet.noneOf(Optimization.class);
+
+        RiProfilingInfo profilingInfo = method.profilingInfo();
+        if (checkDeoptimizations(profilingInfo, RiDeoptReason.UnreachedCode)) {
+            enabledOpts.add(Optimization.RemoveNeverExecutedCode);
+        }
+        if (checkDeoptimizations(profilingInfo, RiDeoptReason.TypeCheckedInliningViolated)) {
+            enabledOpts.add(Optimization.UseTypeCheckedInlining);
+        }
+        if (checkDeoptimizations(profilingInfo, RiDeoptReason.OptimizedTypeCheckViolated)) {
+            enabledOpts.add(Optimization.UseTypeCheckHints);
+        }
+        if (checkDeoptimizations(profilingInfo, RiDeoptReason.NotCompiledExceptionHandler)) {
+            enabledOpts.add(Optimization.UseExceptionProbability);
+        }
+    }
+
+    private OptimisticOptimizations(Set<Optimization> enabledOpts) {
+        this.enabledOpts = enabledOpts;
+    }
+
+    public void log(RiMethod method) {
+        for (Optimization opt: Optimization.values()) {
+            if (!enabledOpts.contains(opt)) {
+                if (GraalOptions.PrintDisabledOptimisticOptimizations) {
+                    TTY.println("WARN: deactivated optimistic optimization %s for %s", opt.name(), CiUtil.format("%H.%n(%p)", method));
+                }
+                disabledOptimisticOptsMetric.increment();
+            }
+        }
+    }
+
+    public boolean removeNeverExecutedCode() {
+        return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
+    }
+
+    public boolean useUseTypeCheckHints() {
+        return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints);
+    }
+
+    public boolean inlineMonomorphicCalls() {
+        return GraalOptions.InlineMonomorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+    }
+
+    public boolean inlinePolymorphicCalls() {
+        return GraalOptions.InlinePolymorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+    }
+
+    public boolean inlineMegamorphicCalls() {
+        return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+    }
+
+    public boolean useExceptionProbability() {
+        return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability);
+    }
+
+    public boolean lessOptimisticThan(OptimisticOptimizations other) {
+        for (Optimization opt: Optimization.values()) {
+            if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean checkDeoptimizations(RiProfilingInfo profilingInfo, RiDeoptReason reason) {
+        return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization;
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Mar 21 13:57:30 2012 +0100
@@ -56,7 +56,6 @@
 import com.oracle.graal.lir.StandardOp.PhiLabelOp;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -745,7 +744,7 @@
     }
 
     @Override
-    public void emitGuardCheck(BooleanNode comp) {
+    public void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason) {
         if (comp instanceof NullCheckNode && !((NullCheckNode) comp).expectedNull) {
             emitNullCheckGuard((NullCheckNode) comp);
         } else if (comp instanceof ConstantNode && comp.asConstant().asBoolean()) {
@@ -753,7 +752,7 @@
         } else {
             // Fall back to a normal branch.
             LIRDebugInfo info = state();
-            LabelRef stubEntry = createDeoptStub(DeoptAction.InvalidateReprofile, info, comp);
+            LabelRef stubEntry = createDeoptStub(RiDeoptAction.InvalidateReprofile, deoptReason, info, comp);
             emitBranch(comp, null, stubEntry, info);
         }
     }
@@ -986,7 +985,7 @@
     }
 
 
-    protected abstract LabelRef createDeoptStub(DeoptAction action, LIRDebugInfo info, Object deoptInfo);
+    protected abstract LabelRef createDeoptStub(RiDeoptAction action, RiDeoptReason reason, LIRDebugInfo info, Object deoptInfo);
 
     @Override
     public Variable emitCallToRuntime(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java	Wed Mar 21 13:57:30 2012 +0100
@@ -84,7 +84,7 @@
             }
             BeginNode ifBlockBegin = findBeginNode(ifNode);
             Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s. IfBegin=%s", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin, ifBlockBegin);
-            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason()));
             otherBegin.replaceAtUsages(ifBlockBegin);
             FixedNode next = otherBegin.next();
             otherBegin.setNext(null);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Wed Mar 21 13:57:30 2012 +0100
@@ -215,12 +215,14 @@
     private final GraalRuntime runtime;
     private final CiAssumptions assumptions;
     private final PhasePlan plan;
+    private final OptimisticOptimizations optimisticOpts;
 
-    public EscapeAnalysisPhase(CiTarget target, GraalRuntime runtime, CiAssumptions assumptions, PhasePlan plan) {
+    public EscapeAnalysisPhase(CiTarget target, GraalRuntime runtime, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
         this.runtime = runtime;
         this.target = target;
         this.assumptions = assumptions;
         this.plan = plan;
+        this.optimisticOpts = optimisticOpts;
     }
 
     public static class EscapeRecord {
@@ -387,7 +389,7 @@
             if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
                 TTY.println("Trying inlining to get a non-escaping object for %s", node);
             }
-            new InliningPhase(target, runtime, invokes, assumptions, plan).apply(graph);
+            new InliningPhase(target, runtime, invokes, assumptions, plan, optimisticOpts).apply(graph);
             new DeadCodeEliminationPhase().apply(graph);
             if (node.isDeleted()) {
                 if (GraalOptions.TraceEscapeAnalysis || GraalOptions.PrintEscapeAnalysis) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Wed Mar 21 13:57:30 2012 +0100
@@ -56,18 +56,20 @@
     private final PhasePlan plan;
     private final WeightComputationPolicy weightComputationPolicy;
     private final InliningPolicy inliningPolicy;
+    private final OptimisticOptimizations optimisticOpts;
 
     // Metrics
     private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed");
     private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered");
     private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
 
-    public InliningPhase(CiTarget target, GraalRuntime runtime, Collection<? extends Invoke> hints, CiAssumptions assumptions, PhasePlan plan) {
+    public InliningPhase(CiTarget target, GraalRuntime runtime, Collection<? extends Invoke> hints, CiAssumptions assumptions, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
         this.target = target;
         this.runtime = runtime;
         this.hints = hints;
         this.assumptions = assumptions;
         this.plan = plan;
+        this.optimisticOpts = optimisticOpts;
         this.weightComputationPolicy = createWeightComputationPolicy();
         this.inliningPolicy = createInliningPolicy();
     }
@@ -139,7 +141,7 @@
     }
 
     private void scanInvoke(Invoke invoke, int level) {
-        InlineInfo info = InliningUtil.getInlineInfo(invoke, level >= 0 ? level : computeInliningLevel(invoke), runtime, assumptions, this);
+        InlineInfo info = InliningUtil.getInlineInfo(invoke, level >= 0 ? level : computeInliningLevel(invoke), runtime, assumptions, this, optimisticOpts);
         if (info != null) {
             assert level == -1 || computeInliningLevel(invoke) == level : "outer FramesStates must match inlining level";
             metricInliningConsidered.increment();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Wed Mar 21 13:57:30 2012 +0100
@@ -28,6 +28,7 @@
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.max.cri.ri.*;
 
 public class LoweringPhase extends Phase {
 
@@ -59,8 +60,8 @@
             }
 
             @Override
-            public Node createGuard(Node condition) {
-                // TODO (thomaswue): Docuemnt why this must not be called on floating nodes.
+            public Node createGuard(Node condition, RiDeoptReason deoptReason) {
+                // TODO (thomaswue): Document why this must not be called on floating nodes.
                 throw new UnsupportedOperationException();
             }
         };
@@ -117,7 +118,7 @@
             }
 
             @Override
-            public Node createGuard(Node condition) {
+            public Node createGuard(Node condition, RiDeoptReason deoptReason) {
                 FixedNode guardAnchor = (FixedNode) getGuardAnchor();
                 if (GraalOptions.OptEliminateGuards) {
                     for (Node usage : condition.usages()) {
@@ -126,7 +127,7 @@
                         }
                     }
                 }
-                GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor));
+                GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, deoptReason));
                 activeGuards.grow();
                 activeGuards.mark(newGuard);
                 return newGuard;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/PhasePlan.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/PhasePlan.java	Wed Mar 21 13:57:30 2012 +0100
@@ -53,11 +53,8 @@
         LOW_LEVEL
     }
 
-    public static final PhasePlan DEFAULT = new PhasePlan();
-
     @SuppressWarnings("unchecked")
     private final ArrayList<Phase>[] phases = new ArrayList[PhasePosition.values().length];
-
     private final Set<Class<? extends Phase>> disabledPhases = new HashSet<>();
 
     public void addPhase(PhasePosition pos, Phase phase) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Wed Mar 21 13:57:30 2012 +0100
@@ -24,29 +24,29 @@
 
 import java.util.*;
 
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.*;
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.ci.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction;
+import com.oracle.max.cri.ri.*;
 
 public class AMD64DeoptimizationStub extends AMD64SlowPath {
     public final Label label = new Label();
     public final LIRDebugInfo info;
-    public final DeoptAction action;
+    public final RiDeoptAction action;
+    public final RiDeoptReason reason;
     public final Object deoptInfo;
 
-    public AMD64DeoptimizationStub(DeoptAction action, LIRDebugInfo info, Object deoptInfo) {
+    public AMD64DeoptimizationStub(RiDeoptAction action, RiDeoptReason reason, LIRDebugInfo info, Object deoptInfo) {
         this.action = action;
+        this.reason = reason;
         this.info = info;
         this.deoptInfo = deoptInfo;
     }
 
-
     private static ArrayList<Object> keepAlive = new ArrayList<>();
 
     @Override
@@ -62,28 +62,9 @@
             // TODO Make this an explicit calling convention instead of using a scratch register
             AMD64Call.directCall(tasm, masm, CiRuntimeCall.SetDeoptInfo, info);
         }
-        int code;
-        switch(action) {
-            case None:
-                code = 0;
-                break;
-            case Recompile:
-                code = 1;
-                break;
-            case InvalidateReprofile:
-                code = 2;
-                break;
-            case InvalidateRecompile:
-                code = 3;
-                break;
-            case InvalidateStopCompiling:
-                code = 4;
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-        masm.movq(scratch, code);
-     // TODO Make this an explicit calling convention instead of using a scratch register
+
+        masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason));
+        // TODO Make this an explicit calling convention instead of using a scratch register
         AMD64Call.directCall(tasm, masm, CiRuntimeCall.Deoptimize, info);
         AMD64Call.shouldNotReachHere(tasm, masm);
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Mar 21 13:57:30 2012 +0100
@@ -66,7 +66,6 @@
 import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp;
 import com.oracle.graal.lir.amd64.AMD64Move.SpillMoveOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
-import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -500,9 +499,9 @@
 
 
     @Override
-    public void emitDeoptimizeOn(Condition cond, DeoptAction action, Object deoptInfo) {
+    public void emitDeoptimizeOn(Condition cond, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo) {
         LIRDebugInfo info = state();
-        LabelRef stubEntry = createDeoptStub(action, info, deoptInfo);
+        LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
         if (cond != null) {
             append(new BranchOp(cond, stubEntry, info));
         } else {
@@ -547,9 +546,9 @@
     }
 
     @Override
-    protected LabelRef createDeoptStub(DeoptAction action, LIRDebugInfo info, Object deoptInfo) {
+    protected LabelRef createDeoptStub(RiDeoptAction action, RiDeoptReason reason, LIRDebugInfo info, Object deoptInfo) {
         assert info.topFrame.bci >= 0 : "invalid bci for deopt framestate";
-        AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, info, deoptInfo);
+        AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo);
         lir.deoptimizationStubs.add(stub);
         return LabelRef.forLabel(stub.label);
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Wed Mar 21 13:57:30 2012 +0100
@@ -35,7 +35,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -52,23 +51,23 @@
         void recordConcreteMethodAssumption(RiResolvedMethod method, RiResolvedType context, RiResolvedMethod impl);
     }
 
-    public static String methodName(RiResolvedMethod method) {
-        return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
-    }
-
     private static String methodName(RiResolvedMethod method, Invoke invoke) {
         if (Debug.isLogEnabled()) {
             if (invoke != null && invoke.stateAfter() != null) {
                 RiMethod parent = invoke.stateAfter().method();
-                return parent.name() + "@" + invoke.bci() + ": " + CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
+                return parent.name() + "@" + invoke.bci() + ": " + methodNameAndCodeSize(method);
             } else {
-                return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
+                return methodNameAndCodeSize(method);
             }
         } else {
             return null;
         }
     }
 
+    private static String methodNameAndCodeSize(RiResolvedMethod method) {
+        return CiUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
+    }
+
     /**
      * Represents an opportunity for inlining at the given invoke, with the given weight and level.
      * The weight is the amortized weight of the additional code - so smaller is better.
@@ -176,7 +175,7 @@
             ValueNode receiver = invoke.callTarget().receiver();
             ReadHubNode objectClass = graph.add(new ReadHubNode(receiver));
             IsTypeNode isTypeNode = graph.unique(new IsTypeNode(objectClass, type));
-            FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode, RiDeoptReason.TypeCheckedInliningViolated));
             AnchorNode anchor = graph.add(new AnchorNode());
             assert invoke.predecessor() != null;
 
@@ -304,7 +303,7 @@
             if (shouldFallbackToInvoke()) {
                 unknownTypeNode = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, 1, notRecordedTypeProbability, false);
             } else {
-                unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile));
+                unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated));
             }
 
             // replace the invoke exception edge
@@ -369,7 +368,7 @@
             ReadHubNode objectClassNode = graph.add(new ReadHubNode(invoke.callTarget().receiver()));
             graph.addBeforeFixed(invoke.node(), objectClassNode);
 
-            FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile));
+            FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated));
             FixedNode dispatchOnType = createDispatchOnType(graph, objectClassNode, new BeginNode[] {calleeEntryNode}, unknownTypeNode);
 
             FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor();
@@ -541,19 +540,19 @@
      * @param callback a callback that is 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, GraalRuntime runtime, CiAssumptions assumptions, InliningCallback callback) {
-        if (!checkInvokeConditions(invoke)) {
-            return null;
-        }
+    public static InlineInfo getInlineInfo(Invoke invoke, int level, GraalRuntime runtime, CiAssumptions assumptions, InliningCallback callback, OptimisticOptimizations optimisticOpts) {
         RiResolvedMethod parent = invoke.stateAfter().method();
         MethodCallTargetNode callTarget = invoke.callTarget();
         RiResolvedMethod targetMethod = callTarget.targetMethod();
-
         if (targetMethod == null) {
             return null;
         }
+        if (!checkInvokeConditions(invoke)) {
+            return null;
+        }
+
         if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) {
-            if (checkTargetConditions(invoke, targetMethod)) {
+            if (checkTargetConditions(invoke, targetMethod, optimisticOpts)) {
                 double weight = callback == null ? 0 : callback.inliningWeight(parent, targetMethod, invoke);
                 return new ExactInlineInfo(invoke, weight, level, targetMethod);
             }
@@ -563,7 +562,7 @@
             RiResolvedType exact = callTarget.receiver().exactType();
             assert exact.isSubtypeOf(targetMethod.holder()) : exact + " subtype of " + targetMethod.holder() + " for " + targetMethod;
             RiResolvedMethod resolved = exact.resolveMethodImpl(targetMethod);
-            if (checkTargetConditions(invoke, resolved)) {
+            if (checkTargetConditions(invoke, resolved, optimisticOpts)) {
                 double weight = callback == null ? 0 : callback.inliningWeight(parent, resolved, invoke);
                 return new ExactInlineInfo(invoke, weight, level, resolved);
             }
@@ -583,7 +582,7 @@
         if (assumptions != null) {
             RiResolvedMethod concrete = holder.uniqueConcreteMethod(targetMethod);
             if (concrete != null) {
-                if (checkTargetConditions(invoke, concrete)) {
+                if (checkTargetConditions(invoke, concrete, optimisticOpts)) {
                     double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
                     return new AssumptionInlineInfo(invoke, weight, level, holder, concrete);
                 }
@@ -592,6 +591,10 @@
         }
 
         // type check based inlining
+        return getTypeCheckedInlineInfo(invoke, level, callback, parent, targetMethod, optimisticOpts);
+    }
+
+    private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, int level, InliningCallback callback, RiResolvedMethod parent, RiResolvedMethod targetMethod, OptimisticOptimizations optimisticOpts) {
         RiProfilingInfo profilingInfo = parent.profilingInfo();
         RiTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci());
         if (typeProfile != null) {
@@ -602,10 +605,10 @@
                 assert types.length == probabilities.length : "length must match";
                 double notRecordedTypeProbability = typeProfile.getNotRecordedProbability();
                 if (types.length == 1 && notRecordedTypeProbability == 0) {
-                    if (GraalOptions.InlineMonomorphicCalls) {
+                    if (optimisticOpts.inlineMonomorphicCalls()) {
                         RiResolvedType type = types[0];
                         RiResolvedMethod concrete = type.resolveMethodImpl(targetMethod);
-                        if (checkTargetConditions(invoke, concrete)) {
+                        if (checkTargetConditions(invoke, concrete, optimisticOpts)) {
                             double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
                             return new TypeGuardInlineInfo(invoke, weight, level, concrete, type);
                         }
@@ -618,7 +621,7 @@
                     }
                 } else {
                     invoke.setMegamorph(true);
-                    if (GraalOptions.InlinePolymorphicCalls && notRecordedTypeProbability == 0 || GraalOptions.InlineMegamorphicCalls && notRecordedTypeProbability > 0) {
+                    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
@@ -644,7 +647,7 @@
                         double totalWeight = 0;
                         boolean canInline = true;
                         for (RiResolvedMethod concrete: concreteMethods) {
-                            if (!checkTargetConditions(invoke, concrete)) {
+                            if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
                                 canInline = false;
                                 break;
                             }
@@ -658,7 +661,7 @@
                             return null;
                         }
                     } else {
-                        if (!GraalOptions.InlinePolymorphicCalls && notRecordedTypeProbability == 0) {
+                        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));
@@ -699,7 +702,7 @@
         return true;
     }
 
-    private static boolean checkTargetConditions(Invoke invoke, RiMethod method) {
+    private static boolean checkTargetConditions(Invoke invoke, RiMethod method, OptimisticOptimizations optimisticOpts) {
         if (method == null) {
             Debug.log("not inlining because method is not resolved");
             return false;
@@ -710,23 +713,28 @@
         }
         RiResolvedMethod resolvedMethod = (RiResolvedMethod) method;
         if (Modifier.isNative(resolvedMethod.accessFlags())) {
-            Debug.log("not inlining %s because it is a native method", methodName(resolvedMethod));
+            Debug.log("not inlining %s because it is a native method", methodName(resolvedMethod, invoke));
             return false;
         }
         if (Modifier.isAbstract(resolvedMethod.accessFlags())) {
-            Debug.log("not inlining %s because it is an abstract method", methodName(resolvedMethod));
+            Debug.log("not inlining %s because it is an abstract method", methodName(resolvedMethod, invoke));
             return false;
         }
         if (!resolvedMethod.holder().isInitialized()) {
-            Debug.log("not inlining %s because of non-initialized class", methodName(resolvedMethod));
+            Debug.log("not inlining %s because of non-initialized class", methodName(resolvedMethod, invoke));
             return false;
         }
         if (!resolvedMethod.canBeInlined()) {
-            Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod));
+            Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod, invoke));
             return false;
         }
         if (computeRecursiveInliningLevel(invoke.stateAfter(), (RiResolvedMethod) method) > GraalOptions.MaximumRecursiveInlining) {
-            Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(resolvedMethod));
+            Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(resolvedMethod, invoke));
+            return false;
+        }
+        OptimisticOptimizations calleeOpts = new OptimisticOptimizations(resolvedMethod);
+        if (calleeOpts.lessOptimisticThan(optimisticOpts)) {
+            Debug.log("not inlining %s because callee uses less optimistic optimizations than caller", methodName(resolvedMethod, invoke));
             return false;
         }
 
@@ -812,7 +820,7 @@
         } else {
             if (unwindNode != null) {
                 UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
-                DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptAction.InvalidateRecompile);
+                DeoptimizeNode deoptimizeNode = new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.NotCompiledExceptionHandler);
                 unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode));
                 // move the deopt upwards if there is a monitor exit that tries to use the "after exception" frame state
                 // (because there is no "after exception" frame state!)
@@ -900,7 +908,7 @@
         NodeInputList<ValueNode> parameters = callTarget.arguments();
         ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0);
         if (!callTarget.isStatic() && firstParam.kind() == CiKind.Object && !firstParam.stamp().nonNull()) {
-            graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false)))));
+            graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false)), RiDeoptReason.ClassCastException)));
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Wed Mar 21 13:57:30 2012 +0100
@@ -26,9 +26,8 @@
 
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.PhasePlan.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
@@ -39,21 +38,21 @@
     private final Compiler compiler;
     private final PhasePlan plan;
     private final RiResolvedMethod method;
+    private final OptimisticOptimizations optimisticOpts;
 
-    public static CompilationTask create(Compiler compiler, PhasePlan plan, RiResolvedMethod method) {
-        return new CompilationTask(compiler, plan, method);
+    public static CompilationTask create(Compiler compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, RiResolvedMethod method) {
+        return new CompilationTask(compiler, plan, optimisticOpts, method);
     }
 
-    private CompilationTask(Compiler compiler, PhasePlan plan, RiResolvedMethod method) {
+    private CompilationTask(Compiler compiler, PhasePlan plan, OptimisticOptimizations optimisticOpts, RiResolvedMethod method) {
         this.compiler = compiler;
         this.plan = plan;
         this.method = method;
+        this.optimisticOpts = optimisticOpts;
     }
 
     public void run() {
         try {
-            GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime());
-            plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
             final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
             if (printCompilation) {
                 TTY.println(String.format("Graal %-70s %-45s %-50s ...", method.holder().name(), method.name(), method.signature().asString()));
@@ -66,7 +65,8 @@
 
                     @Override
                     public CiTargetMethod call() throws Exception {
-                        return compiler.getCompiler().compileMethod(method, -1, plan);
+                        StructuredGraph graph = new StructuredGraph(method);
+                        return compiler.getCompiler().compileMethod(method, graph, -1, plan, optimisticOpts);
                     }
                 });
             } finally {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Mar 21 13:57:30 2012 +0100
@@ -76,6 +76,7 @@
 
     // methodData information
     public int methodDataOopDataOffset;
+    public int methodDataOopTrapHistoryOffset;
     public int dataLayoutHeaderSize;
     public int dataLayoutTagOffset;
     public int dataLayoutFlagsOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Mar 21 13:57:30 2012 +0100
@@ -27,9 +27,6 @@
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.criutils.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
@@ -40,7 +37,11 @@
 import com.oracle.graal.hotspot.ri.*;
 import com.oracle.graal.hotspot.server.*;
 import com.oracle.graal.hotspot.snippets.*;
+import com.oracle.graal.java.*;
 import com.oracle.graal.snippets.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.criutils.*;
 
 /**
  * Exits from the HotSpot VM into Java code.
@@ -93,10 +94,10 @@
                 @Override
                 public void run() {
                     VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime);
-                    GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget(), PhasePlan.DEFAULT);
-                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets(), PhasePlan.DEFAULT);
-                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets(), PhasePlan.DEFAULT);
-                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets(), PhasePlan.DEFAULT);
+                    GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget());
+                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets());
+                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets());
+                    Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets());
                 }
             });
 
@@ -275,7 +276,8 @@
             }
         }
 
-        Runnable task = CompilationTask.create(compiler, getDefaultPhasePlan(), method);
+        final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method);
+        Runnable task = CompilationTask.create(compiler, createHotSpotSpecificPhasePlan(optimisticOpts), optimisticOpts, method);
         if (blocking) {
             task.run();
         } else {
@@ -378,8 +380,11 @@
         return CiConstant.forObject(object);
     }
 
-    private PhasePlan getDefaultPhasePlan() {
+
+    private PhasePlan createHotSpotSpecificPhasePlan(OptimisticOptimizations optimisticOpts) {
         PhasePlan phasePlan = new PhasePlan();
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts);
+        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         if (GraalOptions.Intrinsify) {
             phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java	Wed Mar 21 13:57:30 2012 +0100
@@ -26,10 +26,10 @@
 
 import sun.misc.*;
 
-import com.oracle.max.cri.ri.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.Compiler;
+import com.oracle.max.cri.ri.*;
 
 
 public final class HotSpotMethodData extends CompilerObject {
@@ -80,6 +80,11 @@
         return position >= 0 && position < normalDataSize + extraDataSize;
     }
 
+    public int getDeoptimizationCount(RiDeoptReason reason) {
+        int reasonIndex = compiler.getRuntime().convertDeoptReason(reason);
+        return unsafe.getByte(hotspotMirror, (long) config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
+    }
+
     public HotSpotMethodDataAccessor getNormalData(int position) {
         if (position >= normalDataSize) {
             return null;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Wed Mar 21 13:57:30 2012 +0100
@@ -30,6 +30,7 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.java.bytecode.*;
 
 /**
@@ -213,12 +214,13 @@
 
     @Override
     public RiProfilingInfo profilingInfo() {
-        if (methodData == null) {
+        if (GraalOptions.UseProfilingInformation && methodData == null) {
             methodData = compiler.getVMEntries().RiMethod_methodData(this);
         }
 
         if (methodData == null) {
-            return new HotSpotNoProfilingInfo(compiler);
+            // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in case of a deoptimization.
+            return BaseProfilingInfo.get(RiExceptionSeen.FALSE);
         } else {
             return new HotSpotProfilingInfo(compiler, methodData);
         }
@@ -279,6 +281,18 @@
                 }
             }
         }
+
+        boolean firstDeoptReason = true;
+        for (RiDeoptReason reason: RiDeoptReason.values()) {
+            int count = profilingInfo.getDeoptimizationCount(reason);
+            if (count > 0) {
+                if (firstDeoptReason) {
+                    TTY.println("Deopt History");
+                    firstDeoptReason = false;
+                }
+                TTY.println("  %s: %d", reason.name(), count);
+            }
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotNoProfilingInfo.java	Wed Mar 21 13:49:34 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.ri;
-
-import com.oracle.max.cri.ri.*;
-import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.Compiler;
-
-/**
- * Dummy profiling information in case that a method was not executed frequently enough so that
- * no profiling information does exist yet.
- */
-public final class HotSpotNoProfilingInfo extends CompilerObject implements RiProfilingInfo {
-    /**
-     *
-     */
-    private static final long serialVersionUID = 4357945025049704109L;
-    // Be optimistic and return false for exceptionSeen. A methodDataOop is allocated in case of a deoptimization.
-    private static final HotSpotMethodDataAccessor noData = HotSpotMethodData.getNoDataAccessor(false);
-
-    public HotSpotNoProfilingInfo(Compiler compiler) {
-        super(compiler);
-    }
-
-    @Override
-    public RiTypeProfile getTypeProfile(int bci) {
-        return noData.getTypeProfile(null, -1);
-    }
-
-    @Override
-    public double getBranchTakenProbability(int bci) {
-        return noData.getBranchTakenProbability(null, -1);
-    }
-
-    @Override
-    public double[] getSwitchProbabilities(int bci) {
-        return noData.getSwitchProbabilities(null, -1);
-    }
-
-    @Override
-    public RiExceptionSeen getExceptionSeen(int bci) {
-        return noData.getExceptionSeen(null, -1);
-    }
-
-    @Override
-    public int getExecutionCount(int bci) {
-        return noData.getExecutionCount(null, -1);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java	Wed Mar 21 13:57:30 2012 +0100
@@ -79,6 +79,11 @@
         return dataAccessor.getExecutionCount(methodData, position);
     }
 
+    @Override
+    public int getDeoptimizationCount(RiDeoptReason reason) {
+        return methodData.getDeoptimizationCount(reason);
+    }
+
     private void findBCI(int targetBCI, boolean searchExtraData) {
         assert targetBCI >= 0 : "invalid BCI";
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Wed Mar 21 13:57:30 2012 +0100
@@ -229,7 +229,7 @@
             int displacement = ((HotSpotField) field.field()).offset();
             assert field.kind() != CiKind.Illegal;
             ReadNode memoryRead = graph.add(new ReadNode(field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph), field.stamp()));
-            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false))));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), RiDeoptReason.NullCheckException));
             graph.replaceFixedWithFixed(field, memoryRead);
         } else if (n instanceof StoreFieldNode) {
             StoreFieldNode storeField = (StoreFieldNode) n;
@@ -238,7 +238,7 @@
             }
             HotSpotField field = (HotSpotField) storeField.field();
             WriteNode memoryWrite = graph.add(new WriteNode(storeField.object(), storeField.value(), LocationNode.create(storeField.field(), storeField.field().kind(true), field.offset(), graph)));
-            memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false))));
+            memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), RiDeoptReason.NullCheckException));
             memoryWrite.setStateAfter(storeField.stateAfter());
             graph.replaceFixedWithFixed(storeField, memoryWrite);
 
@@ -277,7 +277,7 @@
                 } else {
                     AnchorNode anchor = graph.add(new AnchorNode());
                     graph.addBeforeFixed(storeIndexed, anchor);
-                    GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)));
+                    GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)), RiDeoptReason.NullCheckException);
                     ReadNode arrayClass = graph.add(new ReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph), StampFactory.objectNonNull()));
                     arrayClass.setGuard(guard);
                     graph.addBeforeFixed(storeIndexed, arrayClass);
@@ -300,7 +300,7 @@
             IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph);
             location.setIndexScalingEnabled(false);
             ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp()));
-            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false))));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), RiDeoptReason.NullCheckException));
             graph.replaceFixedWithFixed(load, memoryRead);
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
@@ -318,7 +318,7 @@
             ReadHubNode objectClassNode = (ReadHubNode) n;
             LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph);
             ReadNode memoryRead = graph.add(new ReadNode(objectClassNode.object(), location, StampFactory.objectNonNull()));
-            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false))));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException));
             graph.replaceFixed(objectClassNode, memoryRead);
         }
     }
@@ -328,7 +328,7 @@
     }
 
     private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) {
-        return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())));
+        return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), RiDeoptReason.BoundsCheckException);
     }
 
     @Override
@@ -424,8 +424,50 @@
     @Override
     public CiTargetMethod compile(RiResolvedMethod method, StructuredGraph graph) {
         final PhasePlan plan = new PhasePlan();
-        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime());
+        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
         plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-        return compiler.getCompiler().compileMethod(method, graph, -1, plan);
+        return compiler.getCompiler().compileMethod(method, graph, -1, plan, OptimisticOptimizations.ALL);
+    }
+
+    @Override
+    public int encodeDeoptActionAndReason(RiDeoptAction action, RiDeoptReason reason) {
+        final int actionShift = 0;
+        final int reasonShift = 3;
+
+        int actionValue = convertDeoptAction(action);
+        int reasonValue = convertDeoptReason(reason);
+        return (~(((reasonValue) << reasonShift) + ((actionValue) << actionShift)));
+    }
+
+    @Override
+    public int convertDeoptAction(RiDeoptAction action) {
+        switch(action) {
+            case None: return 0;
+            case RecompileIfTooManyDeopts: return 1;
+            case InvalidateReprofile: return 2;
+            case InvalidateRecompile: return 3;
+            case InvalidateStopCompiling: return 4;
+            default: throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public int convertDeoptReason(RiDeoptReason reason) {
+        switch(reason) {
+            case None: return 0;
+            case NullCheckException: return 1;
+            case BoundsCheckException: return 2;
+            case ClassCastException: return 3;
+            case ArrayStoreException: return 4;
+            case UnreachedCode: return 5;
+            case TypeCheckedInliningViolated: return 6;
+            case OptimizedTypeCheckViolated: return 7;
+            case NotCompiledExceptionHandler: return 8;
+            case Unresolved: return 9;
+            case JavaSubroutineMismatch: return 10;
+            case ArithmeticException: return 11;
+            case RuntimeConstraint: return 12;
+            default: throw GraalInternalError.shouldNotReachHere();
+        }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Wed Mar 21 13:57:30 2012 +0100
@@ -22,25 +22,29 @@
  */
 package com.oracle.graal.hotspot.ri;
 
+import static com.oracle.graal.hotspot.ri.TemplateFlag.*;
 import static com.oracle.max.cri.ci.CiCallingConvention.Type.*;
 import static com.oracle.max.cri.ci.CiValueUtil.*;
-import static com.oracle.graal.hotspot.ri.TemplateFlag.*;
 
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
 
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiAddress.*;
-import com.oracle.max.cri.ci.CiRegister.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.cri.ri.RiType.*;
-import com.oracle.max.cri.xir.*;
-import com.oracle.max.cri.xir.CiXirAssembler.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.Compiler;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.cri.ci.CiAddress.Scale;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ci.CiRegister.RegisterFlag;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.ri.RiType.Representation;
+import com.oracle.max.cri.xir.*;
+import com.oracle.max.cri.xir.CiXirAssembler.XirConstant;
+import com.oracle.max.cri.xir.CiXirAssembler.XirLabel;
+import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
+import com.oracle.max.cri.xir.CiXirAssembler.XirOperand;
+import com.oracle.max.cri.xir.CiXirAssembler.XirParameter;
 
 public class HotSpotXirGenerator implements RiXirGenerator {
 
@@ -73,6 +77,7 @@
     private final RiRegisterConfig registerConfig;
     private final Compiler compiler;
 
+
     private CiXirAssembler globalAsm;
 
     public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig, Compiler compiler) {
@@ -710,10 +715,10 @@
                     asm.jneq(end, objHub, asm.o(null));
                 }
             }
+
+            RiDeoptReason deoptReason = is(EXACT_HINTS, flags) ? RiDeoptReason.OptimizedTypeCheckViolated : RiDeoptReason.ClassCastException;
             XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
-
-            asm.mov(scratch, wordConst(asm, 2));
-
+            asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.InvalidateReprofile, deoptReason)));
             asm.callRuntime(CiRuntimeCall.Deoptimize, null);
             asm.shouldNotReachHere();
 
@@ -891,7 +896,7 @@
             if (is(BOUNDS_CHECK, flags)) {
                 asm.bindOutOfLine(failBoundsCheck);
                 XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
-                asm.mov(scratch, wordConst(asm, 0));
+                asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.BoundsCheckException)));
                 asm.callRuntime(CiRuntimeCall.Deoptimize, null);
                 asm.shouldNotReachHere();
             }
@@ -1081,7 +1086,7 @@
                 checkSubtype(asm, temp, valueHub, compHub);
                 asm.jneq(store, temp, wordConst(asm, 0));
                 XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
-                asm.mov(scratch, wordConst(asm, 0));
+                asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.ClassCastException)));
                 asm.callRuntime(CiRuntimeCall.Deoptimize, null);
                 asm.jmp(store);
             }
@@ -1162,7 +1167,7 @@
             if (is(BOUNDS_CHECK, flags)) {
                 asm.bindOutOfLine(failBoundsCheck);
                 XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
-                asm.mov(scratch, wordConst(asm, 0));
+                asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.BoundsCheckException)));
                 asm.callRuntime(CiRuntimeCall.Deoptimize, null);
                 asm.shouldNotReachHere();
             }
@@ -1172,7 +1177,7 @@
                 checkSubtype(asm, temp, valueHub, compHub);
                 asm.jneq(store, temp, wordConst(asm, 0));
                 XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10);
-                asm.mov(scratch, wordConst(asm, 0));
+                asm.mov(scratch, wordConst(asm, compiler.getRuntime().encodeDeoptActionAndReason(RiDeoptAction.None, RiDeoptReason.ArrayStoreException)));
                 asm.callRuntime(CiRuntimeCall.Deoptimize, null);
                 asm.shouldNotReachHere();
             }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Mar 21 13:57:30 2012 +0100
@@ -26,14 +26,13 @@
 
 import java.util.*;
 
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.bytecode.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 /**
  * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow
@@ -183,35 +182,28 @@
      * The blocks found in this method, in reverse postorder.
      */
     public final List<Block> blocks;
-
     public final RiResolvedMethod method;
-
-    private final BytecodeStream stream;
-
-    private final RiExceptionHandler[] exceptionHandlers;
-
-    private Block[] blockMap;
-
     public final BitSet canTrap;
-
     public boolean hasJsrBytecodes;
-
     public Block startBlock;
 
-    public final boolean useBranchPrediction;
+    private final OptimisticOptimizations optimisticOpts;
+    private final BytecodeStream stream;
+    private final RiExceptionHandler[] exceptionHandlers;
+    private Block[] blockMap;
 
     /**
      * Creates a new BlockMap instance from bytecode of the given method .
      * @param method the compiler interface method containing the code
      */
-    public BciBlockMapping(RiResolvedMethod method, boolean useBranchPrediction) {
+    public BciBlockMapping(RiResolvedMethod method, OptimisticOptimizations optimisticOpts) {
         this.method = method;
+        this.optimisticOpts = optimisticOpts;
         exceptionHandlers = method.exceptionHandlers();
         stream = new BytecodeStream(method.code());
         this.blockMap = new Block[method.codeSize()];
         this.canTrap = new BitSet(blockMap.length);
         this.blocks = new ArrayList<>();
-        this.useBranchPrediction = useBranchPrediction;
     }
 
     public RiExceptionHandler[] exceptionHandlers() {
@@ -383,8 +375,10 @@
                 case SALOAD:
                 case PUTFIELD:
                 case GETFIELD: {
-                    if (GraalOptions.AllowExplicitExceptionChecks && profilingInfo.getExceptionSeen(bci) != RiExceptionSeen.FALSE) {
-                        canTrap.set(bci);
+                    if (GraalOptions.AllowExplicitExceptionChecks) {
+                        if (!optimisticOpts.useExceptionProbability() || profilingInfo.getExceptionSeen(bci) != RiExceptionSeen.FALSE) {
+                            canTrap.set(bci);
+                        }
                     }
                 }
             }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Wed Mar 21 13:57:30 2012 +0100
@@ -22,9 +22,8 @@
  */
 package com.oracle.graal.java;
 
+import com.oracle.graal.compiler.phases.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 
 public class GraphBuilderConfiguration {
 
@@ -32,22 +31,15 @@
         Default, EagerForSnippets, Eager,
     }
 
-    private final boolean useBranchPrediction;
     private final ResolvePolicy resolving;
     private final PhasePlan plan;
     private RiResolvedType[] skippedExceptionTypes;
 
-    public GraphBuilderConfiguration(boolean useBranchPrediction, ResolvePolicy resolving, PhasePlan plan) {
-        this.useBranchPrediction = useBranchPrediction;
+    public GraphBuilderConfiguration(ResolvePolicy resolving, PhasePlan plan) {
         this.resolving = resolving;
         this.plan = plan;
     }
 
-    public boolean useBranchPrediction() {
-        return useBranchPrediction;
-    }
-
-
     public void setSkippedExceptionTypes(RiResolvedType[] skippedExceptionTypes) {
         this.skippedExceptionTypes = skippedExceptionTypes;
     }
@@ -73,7 +65,7 @@
     }
 
     public static GraphBuilderConfiguration getDefault(PhasePlan plan) {
-        return new GraphBuilderConfiguration(GraalOptions.UseBranchPrediction, ResolvePolicy.Default, plan);
+        return new GraphBuilderConfiguration(ResolvePolicy.Default, plan);
     }
 
     public static GraphBuilderConfiguration getSnippetDefault() {
@@ -81,6 +73,6 @@
     }
 
     public static GraphBuilderConfiguration getSnippetDefault(PhasePlan plan) {
-        return new GraphBuilderConfiguration(false, ResolvePolicy.EagerForSnippets, plan);
+        return new GraphBuilderConfiguration(ResolvePolicy.EagerForSnippets, plan);
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Mar 21 13:57:30 2012 +0100
@@ -28,11 +28,6 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.cri.ri.RiType.Representation;
-import com.oracle.max.criutils.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.util.*;
@@ -42,13 +37,16 @@
 import com.oracle.graal.java.BciBlockMapping.ExceptionBlock;
 import com.oracle.graal.java.bytecode.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.ri.RiType.Representation;
+import com.oracle.max.criutils.*;
 
 /**
  * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
@@ -91,7 +89,8 @@
 
     public static final Map<RiMethod, StructuredGraph> cachedGraphs = new WeakHashMap<>();
 
-    private final GraphBuilderConfiguration config;
+    private final GraphBuilderConfiguration graphBuilderConfig;
+    private final OptimisticOptimizations optimisticOpts;
 
 
     /**
@@ -106,13 +105,9 @@
         }
     }
 
-
-    public GraphBuilderPhase(RiRuntime runtime) {
-        this(runtime, GraphBuilderConfiguration.getDefault());
-    }
-
-    public GraphBuilderPhase(RiRuntime runtime, GraphBuilderConfiguration config) {
-        this.config = config;
+    public GraphBuilderPhase(RiRuntime runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) {
+        this.graphBuilderConfig = graphBuilderConfig;
+        this.optimisticOpts = optimisticOpts;
         this.runtime = runtime;
         this.log = GraalOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
     }
@@ -129,7 +124,7 @@
         methodSynchronizedObject = null;
         exceptionHandlers = null;
         this.currentGraph = graph;
-        this.frameState = new FrameStateBuilder(method, graph, config.eagerResolving());
+        this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving());
         build();
     }
 
@@ -139,7 +134,7 @@
     }
 
     private BciBlockMapping createBlockMap() {
-        BciBlockMapping map = new BciBlockMapping(method, config.useBranchPrediction());
+        BciBlockMapping map = new BciBlockMapping(method, optimisticOpts);
         map.build();
         Debug.dump(map, CiUtil.format("After block building %f %R %H.%n(%P)", method));
 
@@ -255,7 +250,7 @@
     private BeginNode handleException(ValueNode exceptionObject, int bci) {
         assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci";
 
-        if (GraalOptions.UseExceptionProbability) {
+        if (optimisticOpts.useExceptionProbability()) {
             // be conservative if information was not recorded (could result in endless recompiles otherwise)
             if (bci != FrameState.BEFORE_BCI && exceptionObject == null && profilingInfo.getExceptionSeen(bci) == RiExceptionSeen.FALSE) {
                 return null;
@@ -328,7 +323,7 @@
             if (riType instanceof RiResolvedType) {
                 frameState.push(CiKind.Object, append(ConstantNode.forCiConstant(((RiResolvedType) riType).getEncoding(Representation.JavaClass), runtime, currentGraph)));
             } else {
-                append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+                append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
                 frameState.push(CiKind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
             }
         } else if (con instanceof CiConstant) {
@@ -587,7 +582,7 @@
 
     private void genThrow(int bci) {
         ValueNode exception = frameState.apop();
-        FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false))));
+        FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)), RiDeoptReason.NullCheckException));
         append(node);
         append(handleException(exception, bci));
     }
@@ -595,39 +590,39 @@
     private RiType lookupType(int cpi, int bytecode) {
         eagerResolvingForSnippets(cpi, bytecode);
         RiType result = constantPool.lookupType(cpi, bytecode);
-        assert !config.eagerResolvingForSnippets() || result instanceof RiResolvedType;
+        assert !graphBuilderConfig.eagerResolvingForSnippets() || result instanceof RiResolvedType;
         return result;
     }
 
     private RiMethod lookupMethod(int cpi, int opcode) {
         eagerResolvingForSnippets(cpi, opcode);
         RiMethod result = constantPool.lookupMethod(cpi, opcode);
-        assert !config.eagerResolvingForSnippets() || ((result instanceof RiResolvedMethod) && ((RiResolvedMethod) result).holder().isInitialized());
+        assert !graphBuilderConfig.eagerResolvingForSnippets() || ((result instanceof RiResolvedMethod) && ((RiResolvedMethod) result).holder().isInitialized());
         return result;
     }
 
     private RiField lookupField(int cpi, int opcode) {
         eagerResolvingForSnippets(cpi, opcode);
         RiField result = constantPool.lookupField(cpi, opcode);
-        assert !config.eagerResolvingForSnippets() || (result instanceof RiResolvedField && ((RiResolvedField) result).holder().isInitialized());
+        assert !graphBuilderConfig.eagerResolvingForSnippets() || (result instanceof RiResolvedField && ((RiResolvedField) result).holder().isInitialized());
         return result;
     }
 
     private Object lookupConstant(int cpi, int opcode) {
         eagerResolving(cpi, opcode);
         Object result = constantPool.lookupConstant(cpi);
-        assert !config.eagerResolving() || !(result instanceof RiType) || (result instanceof RiResolvedType);
+        assert !graphBuilderConfig.eagerResolving() || !(result instanceof RiType) || (result instanceof RiResolvedType);
         return result;
     }
 
     private void eagerResolving(int cpi, int bytecode) {
-        if (config.eagerResolving()) {
+        if (graphBuilderConfig.eagerResolving()) {
             constantPool.loadReferencedType(cpi, bytecode);
         }
     }
 
     private void eagerResolvingForSnippets(int cpi, int bytecode) {
-        if (config.eagerResolvingForSnippets()) {
+        if (graphBuilderConfig.eagerResolvingForSnippets()) {
             constantPool.loadReferencedType(cpi, bytecode);
         }
     }
@@ -635,7 +630,7 @@
     private static final RiResolvedType[] EMPTY_TYPE_ARRAY = new RiResolvedType[0];
 
     private RiResolvedType[] getTypeCheckHints(RiResolvedType type, int maxHints) {
-        if (!GraalOptions.UseTypeCheckHints || Util.isFinalClass(type)) {
+        if (!optimisticOpts.useUseTypeCheckHints() || Util.isFinalClass(type)) {
             return new RiResolvedType[] {type};
         } else {
             RiResolvedType uniqueSubtype = type.uniqueConcreteSubtype();
@@ -679,7 +674,7 @@
             frameState.apush(checkCast);
         } else {
             ValueNode object = frameState.apop();
-            append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph))))));
+            append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph))), RiDeoptReason.Unresolved)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -697,7 +692,7 @@
             frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph)));
         } else {
             BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode());
-            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile));
+            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved));
             IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new NullCheckNode(object, true)), trueSucc, deopt, 1));
             append(ifNode);
             lastInstr = trueSucc;
@@ -711,7 +706,7 @@
             NewInstanceNode n = currentGraph.add(new NewInstanceNode((RiResolvedType) type));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -752,7 +747,7 @@
             NewArrayNode n = currentGraph.add(new NewObjectArrayNode((RiResolvedType) type, length));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
 
@@ -769,7 +764,7 @@
             FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((RiResolvedType) type, dims));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -783,7 +778,7 @@
             LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (RiResolvedField) field));
             appendOptimizedLoadField(kind, load);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
             frameState.push(kind.stackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
         }
     }
@@ -884,7 +879,7 @@
             StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (RiResolvedField) field, value));
             appendOptimizedStoreField(store);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
         }
     }
 
@@ -926,7 +921,7 @@
         if (initialized) {
             return appendConstant(((RiResolvedType) holder).getEncoding(representation));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
             return null;
         }
     }
@@ -987,7 +982,7 @@
     }
 
     private void genInvokeDeopt(RiMethod unresolvedTarget, boolean withReceiver) {
-        append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+        append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved)));
         frameState.popArguments(unresolvedTarget.signature().argumentSlots(withReceiver), unresolvedTarget.signature().argumentCount(withReceiver));
         CiKind kind = unresolvedTarget.signature().returnKind(false);
         if (kind != CiKind.Void) {
@@ -1024,7 +1019,7 @@
     private void appendInvoke(InvokeKind invokeKind, RiResolvedMethod targetMethod, ValueNode[] args) {
         CiKind resultType = targetMethod.signature().returnKind(false);
         if (GraalOptions.DeoptALot) {
-            DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptAction.None));
+            DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(RiDeoptAction.None, RiDeoptReason.RuntimeConstraint));
             deoptimize.setMessage("invoke " + targetMethod.name());
             append(deoptimize);
             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph));
@@ -1113,7 +1108,7 @@
         ValueNode local = frameState.loadLocal(localIndex);
         JsrScope scope = currentBlock.jsrScope;
         int retAddress = scope.nextReturnAddress();
-        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph))))));
+        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph))), RiDeoptReason.JavaSubroutineMismatch)));
         if (!successor.jsrScope.equals(scope.pop())) {
             throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
         }
@@ -1198,8 +1193,8 @@
 
     private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) {
         assert probability >= 0 && probability <= 1;
-        if (probability == 0 && config.useBranchPrediction()) {
-            return currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile));
+        if (probability == 0 && optimisticOpts.removeNeverExecutedCode()) {
+            return currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.UnreachedCode));
         } else {
             return createTarget(block, stateAfter);
         }
@@ -1403,13 +1398,13 @@
             assert frameState.stackSize() == 1 : frameState;
 
             RiType catchType = block.handler.catchType();
-            if (config.eagerResolving()) {
+            if (graphBuilderConfig.eagerResolving()) {
                 catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF);
             }
             boolean initialized = (catchType instanceof RiResolvedType);
-            if (initialized && config.getSkippedExceptionTypes() != null) {
+            if (initialized && graphBuilderConfig.getSkippedExceptionTypes() != null) {
                 RiResolvedType resolvedCatchType = (RiResolvedType) catchType;
-                for (RiResolvedType skippedType : config.getSkippedExceptionTypes()) {
+                for (RiResolvedType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
                     initialized &= !resolvedCatchType.isSubtypeOf(skippedType);
                     if (!initialized) {
                         break;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Wed Mar 21 13:57:30 2012 +0100
@@ -23,10 +23,11 @@
 package com.oracle.graal.cri;
 
 import com.oracle.graal.graph.*;
+import com.oracle.max.cri.ri.*;
 
 public interface CiLoweringTool {
     GraalRuntime getRuntime();
     Node getGuardAnchor();
-    Node createGuard(Node condition);
+    Node createGuard(Node condition, RiDeoptReason deoptReason);
 }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Mar 21 13:57:30 2012 +0100
@@ -25,28 +25,19 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ri.*;
 
 @NodeInfo(shortName = "Deopt")
 public class DeoptimizeNode extends FixedNode implements Node.IterableNodeType, LIRLowerable {
 
-    public static enum DeoptAction {
-        None,                           // just interpret, do not invalidate nmethod
-        Recompile,                      // recompile the nmethod; need not invalidate
-        InvalidateReprofile,            // invalidate the nmethod, reset IC, maybe recompile
-        InvalidateRecompile,            // invalidate the nmethod, recompile (probably)
-        InvalidateStopCompiling,        // invalidate the nmethod and do not compile
-    }
+    @Data private String message;
+    @Data private final RiDeoptAction action;
+    @Data private final RiDeoptReason reason;
 
-    @Data private String message;
-    @Data private final DeoptAction action;
-
-    public DeoptimizeNode() {
-        this(DeoptAction.InvalidateReprofile);
-    }
-
-    public DeoptimizeNode(DeoptAction action) {
+    public DeoptimizeNode(RiDeoptAction action, RiDeoptReason reason) {
         super(StampFactory.illegal());
         this.action = action;
+        this.reason = reason;
     }
 
     public void setMessage(String message) {
@@ -57,13 +48,17 @@
         return message;
     }
 
-    public DeoptAction action() {
+    public RiDeoptAction action() {
         return action;
     }
 
+    public RiDeoptReason reason() {
+        return reason;
+    }
+
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimizeOn(null, action, message);
+        gen.emitDeoptimizeOn(null, action, reason, message);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Mar 21 13:57:30 2012 +0100
@@ -24,23 +24,25 @@
 
 import com.oracle.graal.cri.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ri.*;
 
 public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, LIRLowerable, Node.IterableNodeType {
 
     @Input private final NodeInputList<BooleanNode> conditions;
+    @Data  private final RiDeoptReason deoptReason;
 
-    public FixedGuardNode(BooleanNode condition) {
+    public FixedGuardNode(BooleanNode condition, RiDeoptReason deoptReason) {
         super(StampFactory.illegal());
         this.conditions = new NodeInputList<>(this, new BooleanNode[] {condition});
+        this.deoptReason = deoptReason;
     }
 
     @Override
     public void generate(LIRGeneratorTool gen) {
         for (BooleanNode condition : conditions()) {
-            gen.emitGuardCheck(condition);
+            gen.emitGuardCheck(condition, deoptReason);
         }
     }
 
@@ -64,7 +66,7 @@
                     if (next != null) {
                         tool.deleteBranch(next);
                     }
-                    setNext(graph().add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)));
+                    setNext(graph().add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, deoptReason)));
                     return;
                 }
             }
@@ -78,7 +80,7 @@
     public void lower(CiLoweringTool tool) {
         AnchorNode newAnchor = graph().add(new AnchorNode());
         for (BooleanNode b : conditions) {
-            newAnchor.addGuard((GuardNode) tool.createGuard(b));
+            newAnchor.addGuard((GuardNode) tool.createGuard(b, deoptReason));
         }
         ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Mar 21 13:57:30 2012 +0100
@@ -27,11 +27,13 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.spi.types.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ri.*;
 
 public final class GuardNode extends FloatingNode implements Canonicalizable, LIRLowerable, TypeFeedbackProvider, Node.IterableNodeType {
 
     @Input private BooleanNode condition;
     @Input(notDataflow = true) private FixedNode anchor;
+    @Data private RiDeoptReason reason;
 
     public FixedNode anchor() {
         return anchor;
@@ -54,15 +56,20 @@
         condition = x;
     }
 
-    public GuardNode(BooleanNode condition, FixedNode anchor) {
+    public RiDeoptReason reason() {
+        return reason;
+    }
+
+    public GuardNode(BooleanNode condition, FixedNode anchor, RiDeoptReason reason) {
         super(StampFactory.illegal());
         this.condition = condition;
         this.anchor = anchor;
+        this.reason = reason;
     }
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitGuardCheck(condition());
+        gen.emitGuardCheck(condition(), reason());
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Wed Mar 21 13:57:30 2012 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ri.*;
 
 
 public class SafeReadNode extends SafeAccessNode implements Lowerable {
@@ -39,7 +40,7 @@
     @Override
     public void lower(CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
-        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)));
+        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException);
         ReadNode read = graph.add(new ReadNode(object(), location(), stamp()));
         read.setGuard(guard);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Wed Mar 21 13:57:30 2012 +0100
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes.extended;
 
-import com.oracle.max.cri.ci.*;
 import com.oracle.graal.cri.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.max.cri.ci.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ri.*;
 
 
 public class SafeWriteNode extends SafeAccessNode implements Lowerable{
@@ -46,7 +47,7 @@
     @Override
     public void lower(CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
-        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)));
+        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException);
         WriteNode write = graph.add(new WriteNode(object(), value(), location()));
         write.setGuard(guard);
         graph.replaceFixedWithFixed(this, write);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Mar 21 13:57:30 2012 +0100
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.nodes.spi;
 
-import com.oracle.max.cri.ci.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.DeoptimizeNode.DeoptAction;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 public abstract class LIRGeneratorTool {
     public abstract CiTarget target();
@@ -79,12 +79,12 @@
 
     public abstract CiValue emitConvert(ConvertNode.Op opcode, CiValue inputVal);
     public abstract void emitMembar(int barriers);
-    public abstract void emitDeoptimizeOn(Condition of, DeoptAction action, Object deoptInfo);
+    public abstract void emitDeoptimizeOn(Condition of, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo);
     public abstract CiValue emitCallToRuntime(CiRuntimeCall runtimeCall, boolean canTrap, CiValue... args);
 
     public abstract void emitIf(IfNode i);
     public abstract void emitConditional(ConditionalNode i);
-    public abstract void emitGuardCheck(BooleanNode comp);
+    public abstract void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason);
 
     public abstract void emitLookupSwitch(LookupSwitchNode i);
     public abstract void emitTableSwitch(TableSwitchNode i);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java	Wed Mar 21 13:57:30 2012 +0100
@@ -22,21 +22,20 @@
  */
 package com.oracle.graal.snippets;
 
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.cri.*;
 import com.oracle.max.cri.ci.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.cri.*;
 
 /**
  * Definition of the snippets that are VM-independent and can be intrinsified by Graal in any VM.
  */
 public class GraalIntrinsics {
-    public static void installIntrinsics(GraalRuntime runtime, CiTarget target, PhasePlan plan) {
+    public static void installIntrinsics(GraalRuntime runtime, CiTarget target) {
         if (GraalOptions.Intrinsify) {
-            Snippets.install(runtime, target, new MathSnippetsX86(), plan);
-            Snippets.install(runtime, target, new DoubleSnippets(), plan);
-            Snippets.install(runtime, target, new FloatSnippets(), plan);
-            Snippets.install(runtime, target, new NodeClassSnippets(), plan);
+            Snippets.install(runtime, target, new MathSnippetsX86());
+            Snippets.install(runtime, target, new DoubleSnippets());
+            Snippets.install(runtime, target, new FloatSnippets());
+            Snippets.install(runtime, target, new NodeClassSnippets());
         }
     }
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Wed Mar 21 13:57:30 2012 +0100
@@ -43,17 +43,17 @@
  */
 public class Snippets {
 
-    public static void install(GraalRuntime runtime, CiTarget target, SnippetsInterface obj, PhasePlan plan) {
+    public static void install(GraalRuntime runtime, CiTarget target, SnippetsInterface obj) {
         Class<? extends SnippetsInterface> clazz = obj.getClass();
         BoxingMethodPool pool = new BoxingMethodPool(runtime);
         if (clazz.isAnnotationPresent(ClassSubstitution.class)) {
-            installSubstitution(runtime, target, plan, clazz, pool, clazz.getAnnotation(ClassSubstitution.class).value());
+            installSubstitution(runtime, target, clazz, pool, clazz.getAnnotation(ClassSubstitution.class).value());
         } else {
-            installSnippets(runtime, target, plan, clazz, pool);
+            installSnippets(runtime, target, clazz, pool);
         }
     }
 
-    private static void installSnippets(GraalRuntime runtime, CiTarget target, PhasePlan plan, Class< ? extends SnippetsInterface> clazz,
+    private static void installSnippets(GraalRuntime runtime, CiTarget target, Class< ? extends SnippetsInterface> clazz,
                     BoxingMethodPool pool) {
         for (Method snippet : clazz.getDeclaredMethods()) {
             int modifiers = snippet.getModifiers();
@@ -62,12 +62,12 @@
             }
             RiResolvedMethod snippetRiMethod = runtime.getRiMethod(snippet);
             if (snippetRiMethod.compilerStorage().get(Graph.class) == null) {
-                buildSnippetGraph(snippetRiMethod, runtime, target, pool, plan);
+                buildSnippetGraph(snippetRiMethod, runtime, target, pool);
             }
         }
     }
 
-    private static void installSubstitution(GraalRuntime runtime, CiTarget target, PhasePlan plan, Class< ? extends SnippetsInterface> clazz,
+    private static void installSubstitution(GraalRuntime runtime, CiTarget target, Class< ? extends SnippetsInterface> clazz,
                     BoxingMethodPool pool, Class<?> original) throws GraalInternalError {
         for (Method snippet : clazz.getDeclaredMethods()) {
             try {
@@ -80,7 +80,7 @@
                     throw new RuntimeException("Snippet must not be abstract or native");
                 }
                 RiResolvedMethod snippetRiMethod = runtime.getRiMethod(snippet);
-                StructuredGraph graph = buildSnippetGraph(snippetRiMethod, runtime, target, pool, plan);
+                StructuredGraph graph = buildSnippetGraph(snippetRiMethod, runtime, target, pool);
                 runtime.getRiMethod(method).compilerStorage().put(Graph.class, graph);
             } catch (NoSuchMethodException e) {
                 throw new RuntimeException("Could not resolve method to substitute with: " + snippet.getName(), e);
@@ -88,13 +88,13 @@
         }
     }
 
-    private static StructuredGraph buildSnippetGraph(final RiResolvedMethod snippetRiMethod, final GraalRuntime runtime, final CiTarget target, final BoxingMethodPool pool, final PhasePlan plan) {
+    private static StructuredGraph buildSnippetGraph(final RiResolvedMethod snippetRiMethod, final GraalRuntime runtime, final CiTarget target, final BoxingMethodPool pool) {
         return Debug.scope("BuildSnippetGraph", snippetRiMethod, new Callable<StructuredGraph>() {
 
             @Override
             public StructuredGraph call() throws Exception {
                 GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault();
-                GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config);
+                GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
                 StructuredGraph graph = new StructuredGraph(snippetRiMethod);
                 graphBuilder.apply(graph);
 
@@ -109,7 +109,7 @@
                     if (holder.isSubtypeOf(runtime.getType(SnippetsInterface.class))) {
                         StructuredGraph targetGraph = (StructuredGraph) targetMethod.compilerStorage().get(Graph.class);
                         if (targetGraph == null) {
-                            targetGraph = buildSnippetGraph(targetMethod, runtime, target, pool, plan);
+                            targetGraph = buildSnippetGraph(targetMethod, runtime, target, pool);
                         }
                         InliningUtil.inline(invoke, targetGraph, true);
                         if (GraalOptions.OptCanonicalizer) {
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -28,6 +28,7 @@
 
 import org.junit.*;
 
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.debug.*;
@@ -123,7 +124,8 @@
                 for (Invoke invoke : graph.getInvokes()) {
                     hints.add(invoke);
                 }
-                new InliningPhase(null, runtime(), hints, null, phasePlan).apply(graph);
+
+                new InliningPhase(null, runtime(), hints, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 new CanonicalizerPhase(null, runtime(), null).apply(graph);
                 Debug.dump(graph, "Graph");
                 new BoxingEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -26,13 +26,14 @@
 
 import org.junit.*;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
-import com.oracle.max.cri.ri.RiCompiledMethod.MethodInvalidatedException;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.ri.RiCompiledMethod.MethodInvalidatedException;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant 0. Then
@@ -78,7 +79,7 @@
         Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class);
         RiResolvedMethod riMethod = runtime.getRiMethod(method);
         StructuredGraph graph = new StructuredGraph(riMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault()).apply(graph);
+        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph);
         new CanonicalizerPhase(null, runtime, null).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
 
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -22,15 +22,16 @@
  */
 package com.oracle.graal.compiler.tests;
 
-import junit.framework.*;
+import junit.framework.Assert;
 
 import org.junit.Test;
 
-import com.oracle.max.cri.ci.*;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.max.cri.ci.*;
 
 /**
  * In these test cases the probability of all invokes is set to a high value, such that an InliningPhase should inline them all.
@@ -121,10 +122,10 @@
             n.node().setProbability(100000);
         }
 
-        new InliningPhase(null, runtime(), null, null, getDefaultPhasePlan()).apply(graph);
+        new InliningPhase(null, runtime(), null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         Debug.dump(graph, "Graph");
-        new EscapeAnalysisPhase(null, runtime(), null, getDefaultPhasePlan()).apply(graph);
+        new EscapeAnalysisPhase(null, runtime(), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         Debug.dump(graph, "Graph");
         int retCount = 0;
         for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphScheduleTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphScheduleTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -50,7 +50,7 @@
                 }
                 block = block.getDominator();
             }
-            Assert.assertTrue(block == aBlock);
+            Assert.assertSame(block, aBlock);
         }
     }
 }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -24,15 +24,16 @@
 
 import java.lang.reflect.*;
 
-import junit.framework.Assert;
+import junit.framework.*;
 
-import com.oracle.max.cri.ri.*;
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.PhasePlan.*;
+import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.cri.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.max.cri.ri.*;
 
 /**
  * Base class for Graal compiler unit tests. These are white box tests
@@ -110,7 +111,7 @@
     protected StructuredGraph parse(Method m) {
         RiResolvedMethod riMethod = runtime.getRiMethod(m);
         StructuredGraph graph = new StructuredGraph(riMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault()).apply(graph);
+        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL).apply(graph);
         return graph;
     }
 
@@ -120,13 +121,13 @@
     protected StructuredGraph parseProfiled(Method m) {
         RiResolvedMethod riMethod = runtime.getRiMethod(m);
         StructuredGraph graph = new StructuredGraph(riMethod);
-        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault()).apply(graph);
+        new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph);
         return graph;
     }
 
     protected PhasePlan getDefaultPhasePlan() {
         PhasePlan plan = new PhasePlan();
-        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault()));
+        plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.ALL));
         return plan;
     }
 }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -26,6 +26,7 @@
 
 import org.junit.*;
 
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.debug.*;
@@ -84,7 +85,7 @@
                 for (Invoke invoke : graph.getInvokes()) {
                     hints.add(invoke);
                 }
-                new InliningPhase(null, runtime(), hints, null, phasePlan).apply(graph);
+                new InliningPhase(null, runtime(), hints, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
                 new CanonicalizerPhase(null, runtime(), null).apply(graph);
                 new PhiStampPhase().apply(graph);
                 new CanonicalizerPhase(null, runtime(), null).apply(graph);
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -26,6 +26,7 @@
 
 import org.junit.*;
 
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.nodes.*;
 
@@ -62,7 +63,7 @@
         for (Invoke invoke : graph.getInvokes()) {
             hints.add(invoke);
         }
-        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan()).apply(graph);
+        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
     }
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -28,6 +28,7 @@
 
 import org.junit.*;
 
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -81,7 +82,7 @@
         for (Invoke invoke : graph.getInvokes()) {
             hints.add(invoke);
         }
-        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan()).apply(graph);
+        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java	Wed Mar 21 13:57:30 2012 +0100
@@ -31,6 +31,7 @@
 import org.junit.Assert;
 import org.junit.Test;
 
+import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
@@ -93,7 +94,7 @@
         for (Invoke invoke : graph.getInvokes()) {
             hints.add(invoke);
         }
-        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan()).apply(graph);
+        new InliningPhase(null, runtime(), hints, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph);
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiDeoptAction.java	Wed Mar 21 13:57:30 2012 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.cri.ri;
+
+
+public enum RiDeoptAction {
+    None,                           // just interpret, do not invalidate nmethod
+    RecompileIfTooManyDeopts,       // recompile the nmethod; need not invalidate
+    InvalidateReprofile,            // invalidate the nmethod, reset IC, maybe recompile
+    InvalidateRecompile,            // invalidate the nmethod, recompile (probably)
+    InvalidateStopCompiling;        // invalidate the nmethod and do not compile
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiDeoptReason.java	Wed Mar 21 13:57:30 2012 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.cri.ri;
+
+
+public enum RiDeoptReason {
+    None,
+    NullCheckException,
+    BoundsCheckException,
+    ClassCastException,
+    ArrayStoreException,
+    UnreachedCode,
+    TypeCheckedInliningViolated,
+    OptimizedTypeCheckViolated,
+    NotCompiledExceptionHandler,
+    Unresolved,
+    JavaSubroutineMismatch,
+    ArithmeticException,
+    RuntimeConstraint;
+}
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java	Wed Mar 21 13:57:30 2012 +0100
@@ -64,4 +64,12 @@
      * @return the estimated execution count or -1 if not available.
      */
     int getExecutionCount(int bci);
+
+    /**
+     * Returns how frequently a method was deoptimized for the given deoptimization reason. This only indicates how
+     * often the method did fall back to the interpreter for the execution and does not indicate how often it was recompiled.
+     * @param reason the reason for which the number of deoptimizations should be queried
+     * @return the number of times the compiled method deoptimized for the given reason.
+     */
+    int getDeoptimizationCount(RiDeoptReason reason);
 }
--- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java	Wed Mar 21 13:49:34 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java	Wed Mar 21 13:57:30 2012 +0100
@@ -195,4 +195,22 @@
      * @return a reference to the compiled and ready-to-run code
      */
     RiCompiledMethod addMethod(RiResolvedMethod method, CiTargetMethod code);
+
+    /**
+     * Encodes a deoptimization action and a deoptimization reason in an integer value.
+     * @return the encoded value as an integer
+     */
+    int encodeDeoptActionAndReason(RiDeoptAction action, RiDeoptReason reason);
+
+    /**
+     * Converts a RiDeoptReason into an integer value.
+     * @return An integer value representing the given RiDeoptReason.
+     */
+    int convertDeoptReason(RiDeoptReason reason);
+
+    /**
+     * Converts a RiDeoptAction into an integer value.
+     * @return An integer value representing the given RiDeoptAction.
+     */
+    int convertDeoptAction(RiDeoptAction action);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/BaseProfilingInfo.java	Wed Mar 21 13:57:30 2012 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.criutils;
+
+import com.oracle.max.cri.ri.*;
+
+
+/**
+ * Dummy profiling information in case that a method was not executed frequently enough so that
+ * no profiling information does exist yet, or in case that the profiling information should not be used.
+ */
+public final class BaseProfilingInfo implements RiProfilingInfo {
+    private static final RiProfilingInfo[] NO_PROFILING_INFO = new RiProfilingInfo[] {
+        new BaseProfilingInfo(RiExceptionSeen.TRUE),
+        new BaseProfilingInfo(RiExceptionSeen.FALSE),
+        new BaseProfilingInfo(RiExceptionSeen.NOT_SUPPORTED)
+    };
+
+    private final RiExceptionSeen exceptionSeen;
+
+    BaseProfilingInfo(RiExceptionSeen exceptionSeen) {
+        this.exceptionSeen = exceptionSeen;
+    }
+
+    @Override
+    public RiTypeProfile getTypeProfile(int bci) {
+        return null;
+    }
+
+    @Override
+    public double getBranchTakenProbability(int bci) {
+        return -1;
+    }
+
+    @Override
+    public double[] getSwitchProbabilities(int bci) {
+        return null;
+    }
+
+    @Override
+    public RiExceptionSeen getExceptionSeen(int bci) {
+        return exceptionSeen;
+    }
+
+    @Override
+    public int getExecutionCount(int bci) {
+        return -1;
+    }
+
+    public static RiProfilingInfo get(RiExceptionSeen exceptionSeen) {
+        return NO_PROFILING_INFO[exceptionSeen.ordinal()];
+    }
+
+    @Override
+    public int getDeoptimizationCount(RiDeoptReason reason) {
+        return 0;
+    }
+}
--- a/mx/commands.py	Wed Mar 21 13:49:34 2012 +0100
+++ b/mx/commands.py	Wed Mar 21 13:57:30 2012 +0100
@@ -384,6 +384,12 @@
         log.close()
     return ret
     
+def jdkhome(args, vm=None):
+    """prints the JDK directory selected for the 'vm' command"""
+    
+    build = _vmbuild if _vmSourcesAvailable else 'product'
+    print join(_graal_home, 'jdk' + mx.java().version, build)
+
 def build(args, vm=None):
     """build the VM binary
     
@@ -894,6 +900,7 @@
         'hsdis': [hsdis, '[att]'],
         'igv' : [igv, ''],
         'intro': [intro, ''],
+        'jdkhome': [jdkhome, ''],
         'dacapo': [dacapo, '[[n] benchmark] [VM options|@DaCapo options]'],
         'scaladacapo': [scaladacapo, '[[n] benchmark] [VM options|@Scala DaCapo options]'],
         'specjvm2008': [specjvm2008, '[VM options|@specjvm2008 options]'],
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -97,12 +97,23 @@
     if (oop_result2->is_valid()) {
       movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD);
     }
+#ifdef GRAAL
     // (thomaswue) Deoptimize in case of an exception.
     restore_live_registers(this, false);
     movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD);
     leave();
-    movl(rscratch1, 2); // InvalidateRecompile
+    movl(rscratch1, Deoptimization::make_trap_request(Deoptimization::Reason_constraint, Deoptimization::Action_reinterpret));
     jump(RuntimeAddress(SharedRuntime::deopt_blob()->uncommon_trap()));
+#else
+    if (frame_size() == no_frame_size) {
+      leave();
+      jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
+    } else if (_stub_id == Runtime1::forward_exception_id) {
+      should_not_reach_here();
+    } else {
+      jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id)));
+    }
+#endif
     bind(L);
   }
   // get oop results if there are any and reset the values in the thread
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -3015,9 +3015,9 @@
 #ifdef GRAAL
   __ jmp(cont);
 
-  int jmp_uncommon_trap_offset = __ pc() - start;
+  int implicit_exception_uncommon_trap_offset = __ pc() - start;
   __ pushptr(Address(r15_thread, in_bytes(JavaThread::ScratchA_offset())));
-  __ movptr(rscratch1, 2); // InvalidateRecompile
+  __ movptr(rscratch1, Address(r15_thread, in_bytes(JavaThread::ScratchB_offset())));
 
   int uncommon_trap_offset = __ pc() - start;
 
@@ -3028,8 +3028,7 @@
 
   assert(r10 == rscratch1, "scratch register should be r10");
   __ movl(c_rarg1, Address(rsp, RegisterSaver::r10_offset_in_bytes()));
-  __ orq(c_rarg1, ~(int32_t)Deoptimization::make_trap_request(Deoptimization::Reason_unreached, Deoptimization::Action_none));
-  __ notq(c_rarg1);
+
   __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
   __ mov(c_rarg0, r15_thread);
   __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
@@ -3039,7 +3038,7 @@
 
   Label after_fetch_unroll_info_call;
   __ jmp(after_fetch_unroll_info_call);
-#endif
+#endif // GRAAL
 
   __ bind(cont);
 
@@ -3245,7 +3244,7 @@
   _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
 #ifdef GRAAL
   _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
-  _deopt_blob->set_jmp_uncommon_trap_offset(jmp_uncommon_trap_offset);
+  _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
 #endif
 }
 
--- a/src/share/vm/c1/c1_Runtime1.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -169,7 +169,7 @@
     RegisterMap reg_map(thread, false);
     frame runtime_frame = thread->last_frame();
     frame caller_frame = runtime_frame.sender(&reg_map);
-    Deoptimization::deoptimize_frame(thread, caller_frame.id());
+    Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
     assert(caller_is_deopted(), "Must be deoptimized");
   }
 }
@@ -434,7 +434,7 @@
     if (osr_nm != NULL) {
       RegisterMap map(thread, false);
       frame fr =  thread->last_frame().sender(&map);
-      Deoptimization::deoptimize_frame(thread, fr.id());
+      Deoptimization::deoptimize_frame(thread, fr.id(), Deoptimization::Reason_constraint);
     }
   JRT_BLOCK_END
   return NULL;
@@ -505,7 +505,7 @@
     // We don't really want to deoptimize the nmethod itself since we
     // can actually continue in the exception handler ourselves but I
     // don't see an easy way to have the desired effect.
-    Deoptimization::deoptimize_frame(thread, caller_frame.id());
+    Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
     assert(caller_is_deopted(), "Must be deoptimized");
 
     return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
@@ -763,7 +763,7 @@
   assert(CodeCache::find_nmethod(caller_frame.pc()) != NULL, "sanity");
 
   // Deoptimize the caller frame.
-  Deoptimization::deoptimize_frame(thread, caller_frame.id());
+  Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
 
   // Return to the now deoptimized frame.
 JRT_END
@@ -975,7 +975,7 @@
       nm->make_not_entrant();
     }
 
-    Deoptimization::deoptimize_frame(thread, caller_frame.id());
+    Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
 
     // Return to the now deoptimized frame.
   }
--- a/src/share/vm/code/codeBlob.hpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/code/codeBlob.hpp	Wed Mar 21 13:57:30 2012 +0100
@@ -407,7 +407,7 @@
 
   // (thomaswue) Offset when graal calls uncommon_trap.
   int _uncommon_trap_offset;
-  int _jmp_uncommon_trap_offset;
+  int _implicit_exception_uncommon_trap_offset;
 
 
   // Creation support
@@ -469,11 +469,11 @@
     assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob");
   }
   address uncommon_trap() const                  { return code_begin() + _uncommon_trap_offset;     }
-  void set_jmp_uncommon_trap_offset(int offset) {
-    _jmp_uncommon_trap_offset = offset;
-    assert(contains(code_begin() + _jmp_uncommon_trap_offset), "must be PC inside codeblob");
+  void set_implicit_exception_uncommon_trap_offset(int offset) {
+    _implicit_exception_uncommon_trap_offset = offset;
+    assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob");
   }
-  address jmp_uncommon_trap() const                  { return code_begin() + _jmp_uncommon_trap_offset;     }
+  address implicit_exception_uncommon_trap() const                  { return code_begin() + _implicit_exception_uncommon_trap_offset;     }
 
 };
 
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -179,6 +179,7 @@
     oop type = CiVirtualObject::type(value);
     int id = CiVirtualObject::id(value);
     klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type));
+    bool isLongArray = klass == Universe::longArrayKlassObj();
 
     for (jint i = 0; i < objects->length(); i++) {
       ObjectValue* obj = (ObjectValue*) objects->at(i);
@@ -198,6 +199,17 @@
       ScopeValue* cur_second = NULL;
       ScopeValue* value = get_hotspot_value(((oop*) values->base(T_OBJECT))[i], total_frame_size, objects, cur_second);
       
+      if (isLongArray && cur_second == NULL) {
+        // we're trying to put ints into a long array... this isn't really valid, but it's used for some optimizations.
+        // add an int 0 constant
+#ifdef BIG_ENDIAN
+        cur_second = value;
+        value = new ConstantIntValue(0);
+#else
+        cur_second = new ConstantIntValue(0);
+#endif
+      }
+
       if (cur_second != NULL) {
         sv->field_values()->append(cur_second);
       }
--- a/src/share/vm/graal/graalCompiler.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -276,7 +276,7 @@
   HotSpotMethodResolved::set_accessFlags(obj, method->access_flags().as_int());
   HotSpotMethodResolved::set_maxLocals(obj, method->max_locals());
   HotSpotMethodResolved::set_maxStackSize(obj, method->max_stack());
-  HotSpotMethodResolved::set_canBeInlined(obj, !CompilerOracle::should_not_inline(method));
+  HotSpotMethodResolved::set_canBeInlined(obj, !method->is_not_compilable() && !CompilerOracle::should_not_inline(method));
   
   method->set_graal_mirror(obj());
   return obj;
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -775,6 +775,7 @@
   set_int(env, config, "classMirrorOffset", in_bytes(Klass::java_mirror_offset()));
   
   set_int(env, config, "methodDataOopDataOffset", in_bytes(methodDataOopDesc::data_offset()));
+  set_int(env, config, "methodDataOopTrapHistoryOffset", in_bytes(methodDataOopDesc::trap_history_offset()));
   set_int(env, config, "dataLayoutHeaderSize", DataLayout::header_size_in_bytes());
   set_int(env, config, "dataLayoutTagOffset", in_bytes(DataLayout::tag_offset()));
   set_int(env, config, "dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset()));
--- a/src/share/vm/oops/methodDataOop.hpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/oops/methodDataOop.hpp	Wed Mar 21 13:57:30 2012 +0100
@@ -1206,7 +1206,11 @@
   // Whole-method sticky bits and flags
 public:
   enum {
+#ifdef GRAAL
+    _trap_hist_limit    = 13,   // decoupled from Deoptimization::Reason_LIMIT
+#else
     _trap_hist_limit    = 17,   // decoupled from Deoptimization::Reason_LIMIT
+#endif
     _trap_hist_mask     = max_jubyte,
     _extra_data_count   = 4     // extra DataLayout headers, for trap history
   }; // Public flag values
@@ -1481,17 +1485,13 @@
   uint inc_trap_count(int reason) {
     // Count another trap, anywhere in this method.
     assert(reason >= 0, "must be single trap");
-    if ((uint)reason < _trap_hist_limit) {
-      uint cnt1 = 1 + _trap_hist._array[reason];
-      if ((cnt1 & _trap_hist_mask) != 0) {  // if no counter overflow...
-        _trap_hist._array[reason] = cnt1;
-        return cnt1;
-      } else {
-        return _trap_hist_mask + (++_nof_overflow_traps);
-      }
+    assert((uint)reason < _trap_hist_limit, "oob");
+    uint cnt1 = 1 + _trap_hist._array[reason];
+    if ((cnt1 & _trap_hist_mask) != 0) {  // if no counter overflow...
+      _trap_hist._array[reason] = cnt1;
+      return cnt1;
     } else {
-      // Could not represent the count in the histogram.
-      return (++_nof_overflow_traps);
+      return _trap_hist_mask + (++_nof_overflow_traps);
     }
   }
 
@@ -1514,6 +1514,10 @@
     return byte_offset_of(methodDataOopDesc, _data[0]);
   }
 
+  static ByteSize trap_history_offset() {
+    return byte_offset_of(methodDataOopDesc, _trap_hist._array);
+  }
+
   static ByteSize invocation_counter_offset() {
     return byte_offset_of(methodDataOopDesc, _invocation_counter);
   }
--- a/src/share/vm/oops/methodOop.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/oops/methodOop.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -51,6 +51,9 @@
 #include "runtime/signature.hpp"
 #include "utilities/quickSort.hpp"
 #include "utilities/xmlstream.hpp"
+#ifdef GRAAL
+#include "graal/graalJavaAccess.hpp"
+#endif
 
 
 // Implementation of methodOopDesc
@@ -658,6 +661,13 @@
       }
   }
   CompilationPolicy::policy()->disable_compilation(this);
+
+#ifdef GRAAL
+  oop graal_mirror = this->graal_mirror();
+  if (graal_mirror != NULL) {
+    HotSpotMethodResolved::set_canBeInlined(graal_mirror, false);
+  }
+#endif
 }
 
 // Revert to using the interpreter and clear out the nmethod
--- a/src/share/vm/opto/runtime.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/opto/runtime.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -1149,7 +1149,7 @@
     frame caller_frame = stub_frame.sender(&reg_map);
 
     // Deoptimize the caller frame.
-    Deoptimization::deoptimize_frame(thread, caller_frame.id());
+    Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_constraint);
   }
 }
 
--- a/src/share/vm/prims/jvmtiEnv.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -1457,7 +1457,7 @@
     // If any of the top 2 frames is a compiled one, need to deoptimize it
     for (int i = 0; i < 2; i++) {
       if (!is_interpreted[i]) {
-        Deoptimization::deoptimize_frame(java_thread, frame_sp[i]);
+        Deoptimization::deoptimize_frame(java_thread, frame_sp[i], Deoptimization::Reason_constraint);
       }
     }
 
--- a/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -1340,7 +1340,7 @@
     if (!vf->fr().can_be_deoptimized()) {
       return JVMTI_ERROR_OPAQUE_FRAME;
     }
-    Deoptimization::deoptimize_frame(java_thread, jvf->fr().id());
+    Deoptimization::deoptimize_frame(java_thread, jvf->fr().id(), Deoptimization::Reason_constraint);
   }
 
   // Get information about method return type
--- a/src/share/vm/prims/jvmtiImpl.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/prims/jvmtiImpl.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -767,7 +767,7 @@
 
       // Schedule deoptimization so that eventually the local
       // update will be written to an interpreter frame.
-      Deoptimization::deoptimize_frame(_jvf->thread(), _jvf->fr().id());
+      Deoptimization::deoptimize_frame(_jvf->thread(), _jvf->fr().id(), Deoptimization::Reason_constraint);
 
       // Now store a new value for the local which will be applied
       // once deoptimization occurs. Note however that while this
--- a/src/share/vm/runtime/compilationPolicy.hpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Wed Mar 21 13:57:30 2012 +0100
@@ -118,7 +118,7 @@
 
 // StackWalkCompPolicy - existing C2 policy
 
-//#ifdef COMPILER2
+#if defined(COMPILER2) || defined(GRAAL)
 class StackWalkCompPolicy : public NonTieredCompPolicy {
  public:
   virtual void method_invocation_event(methodHandle m, JavaThread* thread);
@@ -138,6 +138,6 @@
   // negative filter: should send NOT be inlined?  returns NULL (--> inline) or rejection msg
 
 };
-//#endif
+#endif
 
 #endif // SHARE_VM_RUNTIME_COMPILATIONPOLICY_HPP
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -1133,17 +1133,17 @@
 }
 
 
-void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr) {
+void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr, Deoptimization::DeoptReason reason) {
   assert(fr.can_be_deoptimized(), "checking frame type");
 
-  gather_statistics(Reason_constraint, Action_none, Bytecodes::_illegal);
+  gather_statistics(reason, Action_none, Bytecodes::_illegal);
 
   // Patch the nmethod so that when execution returns to it we will
   // deopt the execution state and return to the interpreter.
   fr.deoptimize(thread);
 }
 
-void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map) {
+void Deoptimization::deoptimize(JavaThread* thread, frame fr, RegisterMap *map, DeoptReason reason) {
   // Deoptimize only if the frame comes from compile code.
   // Do not deoptimize the frame which is already patched
   // during the execution of the loops below.
@@ -1155,12 +1155,12 @@
   if (UseBiasedLocking) {
     revoke_biases_of_monitors(thread, fr, map);
   }
-  deoptimize_single_frame(thread, fr);
+  deoptimize_single_frame(thread, fr, reason);
 
 }
 
 
-void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id) {
+void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason) {
   assert(thread == Thread::current() || SafepointSynchronize::is_at_safepoint(),
          "can only deoptimize other thread at a safepoint");
   // Compute frame and register map based on thread and sp.
@@ -1169,15 +1169,15 @@
   while (fr.id() != id) {
     fr = fr.sender(&reg_map);
   }
-  deoptimize(thread, fr, &reg_map);
+  deoptimize(thread, fr, &reg_map, reason);
 }
 
 
-void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id) {
+void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id, DeoptReason reason) {
   if (thread == Thread::current()) {
-    Deoptimization::deoptimize_frame_internal(thread, id);
+    Deoptimization::deoptimize_frame_internal(thread, id, reason);
   } else {
-    VM_DeoptimizeFrame deopt(thread, id);
+    VM_DeoptimizeFrame deopt(thread, id, reason);
     VMThread::execute(&deopt);
   }
 }
@@ -1502,7 +1502,7 @@
       uint this_trap_count = 0;
       bool maybe_prior_trap = false;
       bool maybe_prior_recompile = false;
-      pdata = query_update_method_data(trap_mdo, trap_bci, reason,
+      pdata = query_update_method_data(trap_mdo, trap_bci, reason, true,
                                    //outputs:
                                    this_trap_count,
                                    maybe_prior_trap,
@@ -1636,25 +1636,31 @@
 Deoptimization::query_update_method_data(methodDataHandle trap_mdo,
                                          int trap_bci,
                                          Deoptimization::DeoptReason reason,
+                                         bool update_total_trap_count,
                                          //outputs:
                                          uint& ret_this_trap_count,
                                          bool& ret_maybe_prior_trap,
                                          bool& ret_maybe_prior_recompile) {
-  uint prior_trap_count = trap_mdo->trap_count(reason);
-  uint this_trap_count  = trap_mdo->inc_trap_count(reason);
+  bool maybe_prior_trap = false;
+  bool maybe_prior_recompile = false;
+  uint this_trap_count = 0;
+  if (update_total_trap_count) {
+    uint prior_trap_count = trap_mdo->trap_count(reason);
+    this_trap_count  = trap_mdo->inc_trap_count(reason);
 
-  // If the runtime cannot find a place to store trap history,
-  // it is estimated based on the general condition of the method.
-  // If the method has ever been recompiled, or has ever incurred
-  // a trap with the present reason , then this BCI is assumed
-  // (pessimistically) to be the culprit.
-  bool maybe_prior_trap      = (prior_trap_count != 0);
-  bool maybe_prior_recompile = (trap_mdo->decompile_count() != 0);
-  ProfileData* pdata = NULL;
-
+    // If the runtime cannot find a place to store trap history,
+    // it is estimated based on the general condition of the method.
+    // If the method has ever been recompiled, or has ever incurred
+    // a trap with the present reason , then this BCI is assumed
+    // (pessimistically) to be the culprit.
+    maybe_prior_trap      = (prior_trap_count != 0);
+    maybe_prior_recompile = (trap_mdo->decompile_count() != 0);
+  }
 
   // For reasons which are recorded per bytecode, we check per-BCI data.
+  ProfileData* pdata = NULL;
   DeoptReason per_bc_reason = reason_recorded_per_bytecode_if_any(reason);
+  assert(per_bc_reason != Reason_none || update_total_trap_count, "must be");
   if (per_bc_reason != Reason_none) {
     // Find the profile data for this BCI.  If there isn't one,
     // try to allocate one from the MDO's set of spares.
@@ -1699,8 +1705,11 @@
   uint ignore_this_trap_count;
   bool ignore_maybe_prior_trap;
   bool ignore_maybe_prior_recompile;
+  // Graal uses the total counts to determine if deoptimizations are happening too frequently -> do not adjust total counts
+  bool update_total_counts = IS_GRAAL(false) NOT_GRAAL(true);
   query_update_method_data(trap_mdo, trap_bci,
                            (DeoptReason)reason,
+                           update_total_counts,
                            ignore_this_trap_count,
                            ignore_maybe_prior_trap,
                            ignore_maybe_prior_recompile);
@@ -1813,6 +1822,21 @@
 Deoptimization::DeoptAction Deoptimization::_unloaded_action
   = Deoptimization::Action_reinterpret;
 const char* Deoptimization::_trap_reason_name[Reason_LIMIT] = {
+#ifdef GRAAL
+  "none",
+  "null_check",
+  "range_check",
+  "class_check",
+  "array_check",
+  "unreached",
+  "type_checked_inlining",
+  "optimized_type_check",
+  "not_compiled_exception_handler",
+  "unresolved",
+  "jsr_mismatch",
+  "div0_check",
+  "constraint"
+#else
   // Note:  Keep this in sync. with enum DeoptReason.
   "none",
   "null_check",
@@ -1831,6 +1855,7 @@
   "age",
   "predicate",
   "loop_limit_check"
+#endif
 };
 const char* Deoptimization::_trap_action_name[Action_LIMIT] = {
   // Note:  Keep this in sync. with enum DeoptAction.
--- a/src/share/vm/runtime/deoptimization.hpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/deoptimization.hpp	Wed Mar 21 13:57:30 2012 +0100
@@ -37,8 +37,35 @@
   friend class VMStructs;
 
  public:
-  // What condition caused the deoptimization?
+  // What condition caused the deoptimization
   enum DeoptReason {
+#ifdef GRAAL
+    Reason_many = -1,             // indicates presence of several reasons
+    Reason_none = 0,              // indicates absence of a relevant deopt.
+    // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits.
+    // This is more complicated for Graal as Graal may deoptimize to *some* bytecode before the
+    // bytecode that actually caused the deopt (with inlining, Graal may even deoptimize to a
+    // bytecode in another method):
+    //  - bytecode y in method b() causes deopt
+    //  - Graal deoptimizes to bytecode x in method a()
+    // -> the deopt reason will be recorded for method a() at bytecode x
+    Reason_null_check,
+    Reason_range_check,
+    Reason_class_check,
+    Reason_array_check,
+    Reason_unreached,
+    Reason_type_checked_inlining,
+    Reason_optimized_type_check,
+
+    // recorded per method
+    Reason_not_compiled_exception_handler,
+    Reason_unresolved,
+    Reason_jsr_mismatch,
+    Reason_div0_check,
+    Reason_constraint,
+    Reason_LIMIT,
+    Reason_RECORDED_LIMIT = Reason_optimized_type_check
+#else
     Reason_many = -1,             // indicates presence of several reasons
     Reason_none = 0,              // indicates absence of a relevant deopt.
     // Next 7 reasons are recorded per bytecode in DataLayout::trap_bits
@@ -50,7 +77,7 @@
     Reason_intrinsic,             // saw unexpected operand to intrinsic (@bci)
     Reason_bimorphic,             // saw unexpected object class in bimorphic inlining (@bci)
 
-    Reason_unloaded,              // unloaded class or constant pool entry
+    Reason_unloaded,              // unloaded or class constant pool entry
     Reason_uninitialized,         // bad class state (uninitialized)
     Reason_unreached,             // code is not reached, compiler
     Reason_unhandled,             // arbitrary compiler limitation
@@ -60,12 +87,13 @@
     Reason_predicate,             // compiler generated predicate failed
     Reason_loop_limit_check,      // compiler generated loop limits check failed
     Reason_LIMIT,
+    Reason_RECORDED_LIMIT = Reason_bimorphic  // some are not recorded per bc
+#endif
     // Note:  Keep this enum in sync. with _trap_reason_name.
-    Reason_RECORDED_LIMIT = Reason_bimorphic  // some are not recorded per bc
     // Note:  Reason_RECORDED_LIMIT should be < 8 to fit into 3 bits of
     // DataLayout::trap_bits.  This dependency is enforced indirectly
     // via asserts, to avoid excessive direct header-to-header dependencies.
-    // See Deoptimization::trap_state_reason and class DataLayout.
+    // See Deoptimization::trap_state_reason and class DataLayout
   };
 
   // What action must be taken by the runtime?
@@ -99,11 +127,11 @@
   static int deoptimize_dependents();
 
   // Deoptimizes a frame lazily. nmethod gets patched deopt happens on return to the frame
-  static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map);
+  static void deoptimize(JavaThread* thread, frame fr, RegisterMap *reg_map, DeoptReason reason);
 
   private:
   // Does the actual work for deoptimizing a single frame
-  static void deoptimize_single_frame(JavaThread* thread, frame fr);
+  static void deoptimize_single_frame(JavaThread* thread, frame fr, DeoptReason reason);
 
   // Helper function to revoke biases of all monitors in frame if UseBiasedLocking
   // is enabled
@@ -233,11 +261,11 @@
   // Only called from VMDeoptimizeFrame
   // @argument thread.     Thread where stub_frame resides.
   // @argument id.         id of frame that should be deoptimized.
-  static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id);
+  static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason);
 
-  // If thread is not the current thread then execute
+  // if thread is not the current thread then execute
   // VM_DeoptimizeFrame otherwise deoptimize directly.
-  static void deoptimize_frame(JavaThread* thread, intptr_t* id);
+  static void deoptimize_frame(JavaThread* thread, intptr_t* id, DeoptReason reason);
 
   // Statistics
   static void gather_statistics(DeoptReason reason, DeoptAction action,
@@ -251,37 +279,60 @@
 
   // trap_request codes
   static DeoptReason trap_request_reason(int trap_request) {
-    if (trap_request < 0)
+    if (trap_request < 0) {
       return (DeoptReason)
         ((~(trap_request) >> _reason_shift) & right_n_bits(_reason_bits));
-    else
+    } else {
+#ifdef GRAAL
+      ShouldNotReachHere();
+      return Reason_none;
+#else
       // standard reason for unloaded CP entry
       return Reason_unloaded;
+#endif // GRAAL
+    }
   }
   static DeoptAction trap_request_action(int trap_request) {
-    if (trap_request < 0)
+    if (trap_request < 0) {
       return (DeoptAction)
         ((~(trap_request) >> _action_shift) & right_n_bits(_action_bits));
-    else
+    } else {
+#ifdef GRAAL
+      ShouldNotReachHere();
+      return Action_make_not_compilable;
+#else
       // standard action for unloaded CP entry
       return _unloaded_action;
+#endif // GRAAL
+    }
   }
   static int trap_request_index(int trap_request) {
-    if (trap_request < 0)
+    if (trap_request < 0) {
       return -1;
-    else
+    } else {
+#ifdef GRAAL
+      ShouldNotReachHere();
+      return -1;
+#else
       return trap_request;
+#endif // GRAAL
+    }
   }
   static int make_trap_request(DeoptReason reason, DeoptAction action,
                                int index = -1) {
+#ifdef GRAAL
+    assert(index == -1, "Graal does not use index");
+#endif
+
     assert((1 << _reason_bits) >= Reason_LIMIT, "enough bits");
     assert((1 << _action_bits) >= Action_LIMIT, "enough bits");
     int trap_request;
-    if (index != -1)
+    if (index != -1) {
       trap_request = index;
-    else
+    } else {
       trap_request = (~(((reason) << _reason_shift)
                         + ((action) << _action_shift)));
+    }
     assert(reason == trap_request_reason(trap_request), "valid reason");
     assert(action == trap_request_action(trap_request), "valid action");
     assert(index  == trap_request_index(trap_request),  "valid index");
@@ -337,6 +388,7 @@
   static ProfileData* query_update_method_data(methodDataHandle trap_mdo,
                                                int trap_bci,
                                                DeoptReason reason,
+                                               bool update_total_trap_count,
                                                //outputs:
                                                uint& ret_this_trap_count,
                                                bool& ret_maybe_prior_trap,
--- a/src/share/vm/runtime/safepoint.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/safepoint.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -1060,7 +1060,7 @@
     // as otherwise we may never deliver it.
     if (thread()->has_async_condition()) {
       ThreadInVMfromJavaNoAsyncException __tiv(thread());
-      Deoptimization::deoptimize_frame(thread(), caller_fr.id());
+      Deoptimization::deoptimize_frame(thread(), caller_fr.id(), Deoptimization::Reason_constraint);
     }
 
     // If an exception has been installed we must check for a pending deoptimization
--- a/src/share/vm/runtime/sharedRuntime.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -665,7 +665,7 @@
     RegisterMap reg_map(thread);
     frame runtime_frame = thread->last_frame();
     frame caller_frame = runtime_frame.sender(&reg_map);
-    Deoptimization::deoptimize_frame(thread, caller_frame.id());
+    Deoptimization::deoptimize_frame(thread, caller_frame.id(), Deoptimization::Reason_not_compiled_exception_handler);
     return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
   }
 
@@ -789,14 +789,17 @@
   throw_and_post_jvmti_exception(thread, exception);
 JRT_END
 
-address SharedRuntime::deoptimization_continuation(JavaThread* thread, address pc, nmethod* nm)
-{
+#ifdef GRAAL
+address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason) {
+  assert(deopt_reason > Deoptimization::Reason_none && deopt_reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
   if (TraceSignals) {
     tty->print_cr(err_msg("Deoptimizing on implicit exception at relative pc=%d in method %s", pc - nm->entry_point(), nm->method()->name()->as_C_string()));
   }
   thread->_ScratchA = (intptr_t)pc;
-  return (SharedRuntime::deopt_blob()->jmp_uncommon_trap());
+  thread->_ScratchB = Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret);
+  return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap());
 }
+#endif
 
 JRT_ENTRY(void, SharedRuntime::throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual))
   assert(thread == JavaThread::current() && required->is_oop() && actual->is_oop(), "bad args");
@@ -891,7 +894,7 @@
           _implicit_null_throws++;
 #endif
 #ifdef GRAAL
-          target_pc = deoptimization_continuation(thread, pc, nm);
+          target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_null_check);
 #else
           target_pc = nm->continuation_for_implicit_exception(pc);
 #endif
@@ -914,7 +917,7 @@
         if (TraceSignals) {
           tty->print_cr("graal implicit div0");
         }
-        target_pc = deoptimization_continuation(thread, pc, nm);
+        target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check);
 #else
         target_pc = nm->continuation_for_implicit_exception(pc);
 #endif
--- a/src/share/vm/runtime/sharedRuntime.hpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Wed Mar 21 13:57:30 2012 +0100
@@ -187,11 +187,13 @@
   static void    throw_NullPointerException(JavaThread* thread);
   static void    throw_NullPointerException_at_call(JavaThread* thread);
   static void    throw_StackOverflowError(JavaThread* thread);
-  static address deoptimization_continuation(JavaThread* thread, address pc, nmethod* nm);
   static void    throw_WrongMethodTypeException(JavaThread* thread, oopDesc* required, oopDesc* actual);
   static address continuation_for_implicit_exception(JavaThread* thread,
                                                      address faulting_pc,
                                                      ImplicitExceptionKind exception_kind);
+#ifdef GRAAL
+  static address deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason);
+#endif
 
   // Shared stub locations
   static address get_poll_stub(address pc);
--- a/src/share/vm/runtime/thread.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/thread.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -2058,7 +2058,7 @@
           RegisterMap reg_map(this, UseBiasedLocking);
           frame compiled_frame = f.sender(&reg_map);
           if (compiled_frame.can_be_deoptimized()) {
-            Deoptimization::deoptimize(this, compiled_frame, &reg_map);
+            Deoptimization::deoptimize(this, compiled_frame, &reg_map, Deoptimization::Reason_constraint);
           }
         }
       }
@@ -2490,7 +2490,7 @@
         trace_frames();
         trace_stack();
       }
-      Deoptimization::deoptimize(this, *fst.current(), fst.register_map());
+      Deoptimization::deoptimize(this, *fst.current(), fst.register_map(), Deoptimization::Reason_constraint);
     }
   }
 
@@ -2520,7 +2520,7 @@
   StackFrameStream fst(this, UseBiasedLocking);
   for(; !fst.is_done(); fst.next()) {
     if (fst.current()->should_be_deoptimized()) {
-      Deoptimization::deoptimize(this, *fst.current(), fst.register_map());
+      Deoptimization::deoptimize(this, *fst.current(), fst.register_map(), Deoptimization::Reason_constraint);
     }
   }
 }
--- a/src/share/vm/runtime/vmStructs.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -2452,26 +2452,32 @@
   declare_constant(Location::on_stack)                                    \
   declare_constant(Location::in_register)                                 \
                                                                           \
-  declare_constant(Deoptimization::Reason_many)                           \
-  declare_constant(Deoptimization::Reason_none)                           \
-  declare_constant(Deoptimization::Reason_null_check)                     \
-  declare_constant(Deoptimization::Reason_null_assert)                    \
-  declare_constant(Deoptimization::Reason_range_check)                    \
-  declare_constant(Deoptimization::Reason_class_check)                    \
-  declare_constant(Deoptimization::Reason_array_check)                    \
-  declare_constant(Deoptimization::Reason_intrinsic)                      \
-  declare_constant(Deoptimization::Reason_bimorphic)                      \
-  declare_constant(Deoptimization::Reason_unloaded)                       \
-  declare_constant(Deoptimization::Reason_uninitialized)                  \
-  declare_constant(Deoptimization::Reason_unreached)                      \
-  declare_constant(Deoptimization::Reason_unhandled)                      \
-  declare_constant(Deoptimization::Reason_constraint)                     \
-  declare_constant(Deoptimization::Reason_div0_check)                     \
-  declare_constant(Deoptimization::Reason_age)                            \
-  declare_constant(Deoptimization::Reason_predicate)                      \
-  declare_constant(Deoptimization::Reason_loop_limit_check)               \
-  declare_constant(Deoptimization::Reason_LIMIT)                          \
-  declare_constant(Deoptimization::Reason_RECORDED_LIMIT)                 \
+  /* TODO (chaeubl) those constants should be graal/c1/c2 specific */         \
+  /*declare_constant(Deoptimization::Reason_many)*/                           \
+  /*declare_constant(Deoptimization::Reason_none)*/                           \
+  /*declare_constant(Deoptimization::Reason_null_check)*/                     \
+  /*declare_constant(Deoptimization::Reason_range_check)*/                    \
+  /*declare_constant(Deoptimization::Reason_class_check)*/                    \
+  /*declare_constant(Deoptimization::Reason_array_check)*/                    \
+  /*declare_constant(Deoptimization::Reason_unreached)*/                      \
+  /*declare_constant(Deoptimization::Reason_constraint)*/                     \
+  /*declare_constant(Deoptimization::Reason_div0_check)*/                     \
+  /*declare_constant(Deoptimization::Reason_type_checked_inlining)*/          \
+  /*declare_constant(Deoptimization::Reason_optimized_type_check)*/           \
+  /*declare_constant(Deoptimization::Reason_not_compiled_exception_handler)*/ \
+  /*declare_constant(Deoptimization::Reason_unresolved)*/                     \
+  /*declare_constant(Deoptimization::Reason_jsr_mismatch)*/                   \
+  /*declare_constant(Deoptimization::Reason_LIMIT)*/                          \
+  /*declare_constant(Deoptimization::Reason_RECORDED_LIMIT)*/                 \
+  /*declare_constant(Deoptimization::Reason_null_assert)*/                    \
+  /*declare_constant(Deoptimization::Reason_intrinsic)*/                      \
+  /*declare_constant(Deoptimization::Reason_bimorphic)*/                      \
+  /*declare_constant(Deoptimization::Reason_unloaded)*/                       \
+  /*declare_constant(Deoptimization::Reason_uninitialized) */                 \
+  /*declare_constant(Deoptimization::Reason_unhandled)*/                      \
+  /*declare_constant(Deoptimization::Reason_age)*/                            \
+  /*declare_constant(Deoptimization::Reason_predicate)*/                      \
+  /*declare_constant(Deoptimization::Reason_loop_limit_check)*/               \
                                                                           \
   /*********************/                                                 \
   /* Matcher (C2 only) */                                                 \
--- a/src/share/vm/runtime/vm_operations.cpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/vm_operations.cpp	Wed Mar 21 13:57:30 2012 +0100
@@ -117,14 +117,16 @@
 }
 
 
-VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id) {
+VM_DeoptimizeFrame::VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason) {
   _thread = thread;
   _id     = id;
+  _reason = reason;
 }
 
 
 void VM_DeoptimizeFrame::doit() {
-  Deoptimization::deoptimize_frame_internal(_thread, _id);
+  assert(_reason > Deoptimization::Reason_none && _reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
+  Deoptimization::deoptimize_frame_internal(_thread, _id, (Deoptimization::DeoptReason)_reason);
 }
 
 
@@ -156,7 +158,7 @@
             if (fst.current()->can_be_deoptimized()) {
               if (fcount++ == fnum) {
                 fcount = 0;
-                Deoptimization::deoptimize(thread, *fst.current(), fst.register_map());
+                Deoptimization::deoptimize(thread, *fst.current(), fst.register_map(), Deoptimization::Reason_constraint);
               }
             }
           }
--- a/src/share/vm/runtime/vm_operations.hpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/runtime/vm_operations.hpp	Wed Mar 21 13:57:30 2012 +0100
@@ -251,7 +251,8 @@
  private:
   JavaThread* _thread;
   intptr_t*   _id;
-  VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id);
+  int _reason;
+  VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id, int reason);
 
  public:
   VMOp_Type type() const                         { return VMOp_DeoptimizeFrame; }
--- a/src/share/vm/utilities/macros.hpp	Wed Mar 21 13:49:34 2012 +0100
+++ b/src/share/vm/utilities/macros.hpp	Wed Mar 21 13:57:30 2012 +0100
@@ -76,8 +76,10 @@
 
 #ifdef GRAAL
 #define IS_GRAAL(code) code
+#define NOT_GRAAL(code)
 #else
 #define IS_GRAAL(code)
+#define NOT_GRAAL(code) code
 #endif
 
 #ifdef TIERED