changeset 5130:ab038e0d6b43

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 21 Mar 2012 11:28:22 +0100
parents 51111665eda6 (current diff) 7b2efb5ff2ea (diff)
children e307e8104e12
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotNoProfilingInfo.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java src/share/vm/code/nmethod.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/runtime/deoptimization.cpp src/share/vm/utilities/macros.hpp
diffstat 86 files changed, 989 insertions(+), 505 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Wed Mar 21 10:47:02 2012 +0100
+++ b/.hgignore	Wed Mar 21 11:28:22 2012 +0100
@@ -1,4 +1,5 @@
 ^mx/env
+^mx/ecj.jar
 ^mx/includes
 ^build/
 ^dist/
@@ -49,5 +50,6 @@
 ^visualizer/build/
 ^visualizer/dist/
 ^visualizer/nbplatform/
+^src/share/tools/IdealGraphVisualizer/nbplatform/
 ^.hgtip
 .DS_Store
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Mar 21 11:28:22 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>() {
@@ -126,7 +122,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);
@@ -137,6 +133,10 @@
 
         new PhiStampPhase().apply(graph);
 
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(target, runtime, assumptions).apply(graph);
+        }
+
         if (GraalOptions.ProbabilityAnalysis && graph.start().probability() == 0) {
             new ComputeProbabilityPhase().apply(graph);
         }
@@ -154,7 +154,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);
         }
@@ -174,7 +174,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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java	Wed Mar 21 11:28:22 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;
@@ -140,6 +142,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;
 
@@ -148,13 +151,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 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Mar 21 11:28:22 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.*;
@@ -750,7 +749,7 @@
     }
 
     @Override
-    public void emitGuardCheck(BooleanNode comp, long leafGraphId) {
+    public void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason, long leafGraphId) {
         if (comp instanceof NullCheckNode && !((NullCheckNode) comp).expectedNull) {
             emitNullCheckGuard((NullCheckNode) comp, leafGraphId);
         } else if (comp instanceof ConstantNode && comp.asConstant().asBoolean()) {
@@ -759,7 +758,7 @@
         } else {
             // Fall back to a normal branch.
             LIRDebugInfo info = state(leafGraphId);
-            LabelRef stubEntry = createDeoptStub(DeoptAction.InvalidateReprofile, info, comp);
+            LabelRef stubEntry = createDeoptStub(RiDeoptAction.InvalidateReprofile, deoptReason, info, comp);
             emitBranch(comp, null, stubEntry, info);
         }
     }
@@ -991,7 +990,8 @@
         return argList;
     }
 
-    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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java	Wed Mar 21 11:28:22 2012 +0100
@@ -49,25 +49,30 @@
         }
 
         for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) {
-            visitDeoptBranch(findBeginNode(d), d, graph);
+            visitDeoptBegin(findBeginNode(d), d, graph);
         }
 
         new DeadCodeEliminationPhase().apply(graph);
     }
 
-    private void visitDeoptBranch(BeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) {
+    private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) {
         if (deoptBegin instanceof MergeNode) {
             MergeNode mergeNode = (MergeNode) deoptBegin;
-            Debug.log("Eliminating %s followed by %s", mergeNode, deopt);
+            Debug.log("Visiting %s followed by %s", mergeNode, deopt);
             List<EndNode> ends = mergeNode.forwardEnds().snapshot();
             for (EndNode end : ends) {
                 if (!end.isDeleted()) {
                     BeginNode beginNode = findBeginNode(end);
-                    visitDeoptBranch(beginNode, deopt, graph);
+                    if (!(beginNode instanceof MergeNode)) {
+                        visitDeoptBegin(beginNode, deopt, graph);
+                    }
                 }
             }
-            if (!deopt.isDeleted()) {
-                visitDeoptBranch(findBeginNode(deopt), deopt, graph);
+            if (mergeNode.isDeleted()) {
+                if (!deopt.isDeleted()) {
+                    Debug.log("Merge deleted, deopt moved to %s", findBeginNode(deopt));
+                    visitDeoptBegin(findBeginNode(deopt), deopt, graph);
+                }
             }
         } else if (deoptBegin.predecessor() instanceof IfNode) {
             IfNode ifNode = (IfNode) deoptBegin.predecessor();
@@ -79,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, deopt.leafGraphId()));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.leafGraphId()));
             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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/EscapeAnalysisPhase.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Wed Mar 21 11:28:22 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,7 +60,7 @@
             }
 
             @Override
-            public Node createGuard(Node condition, long leafGraphId) {
+            public Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId) {
                 // 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, long leafGraphId) {
+            public Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId) {
                 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, leafGraphId));
+                GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, deoptReason, leafGraphId));
                 activeGuards.grow();
                 activeGuards.mark(newGuard);
                 return newGuard;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/PhasePlan.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/PhasePlan.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Mar 21 11:28:22 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.*;
@@ -498,19 +497,20 @@
         return result;
     }
 
+
     @Override
-    public void emitDeoptimizeOn(Condition cond, DeoptAction action, Object deoptInfo) {
+    public void emitDeoptimizeOn(Condition cond, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo) {
         assert cond != null;
         LIRDebugInfo info = state();
-        LabelRef stubEntry = createDeoptStub(action, info, deoptInfo);
+        LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
         append(new BranchOp(cond, stubEntry, info));
     }
 
 
     @Override
-    public void emitDeoptimize(DeoptAction action, Object deoptInfo, long leafGraphId) {
+    public void emitDeoptimize(RiDeoptAction action, RiDeoptReason reason, Object deoptInfo, long leafGraphId) {
         LIRDebugInfo info = state(leafGraphId);
-        LabelRef stubEntry = createDeoptStub(action, info, deoptInfo);
+        LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
         append(new JumpOp(stubEntry, info));
     }
 
@@ -551,9 +551,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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Wed Mar 21 11:28:22 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, invoke.leafGraphId()));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(isTypeNode, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
             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, invoke.leafGraphId()));
+                unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
             }
 
             // 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, invoke.leafGraphId()));
+            FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
             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, invoke.leafGraphId());
+                DeoptimizeNode deoptimizeNode = new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.NotCompiledExceptionHandler, invoke.leafGraphId());
                 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)), invoke.leafGraphId())));
+            graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(firstParam, false)), RiDeoptReason.ClassCastException, invoke.leafGraphId())));
         }
     }
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java	Wed Mar 21 11:28:22 2012 +0100
@@ -57,7 +57,7 @@
 
     @Override
     public boolean add(T node) {
-        assert !node.isDeleted();
+        assert node == null || !node.isDeleted();
         self.incModCount();
         return super.add(node);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Wed Mar 21 11:28:22 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;
@@ -41,7 +38,11 @@
 import com.oracle.graal.hotspot.server.*;
 import com.oracle.graal.hotspot.snippets.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
 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.
@@ -122,10 +123,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());
                 }
             });
 
@@ -298,15 +299,15 @@
 
                 public void run() {
                     try {
-                        final PhasePlan plan = getDefaultPhasePlan();
-                        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime());
-                        plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+                        final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method);
+                        final PhasePlan plan = createHotSpotSpecificPhasePlan(optimisticOpts);
                         long startTime = System.nanoTime();
                         int index = compiledMethodCount++;
                         final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed();
                         if (printCompilation) {
                             TTY.println(String.format("Graal %4d %-70s %-45s %-50s ...", index, method.holder().name(), method.name(), method.signature().asString()));
                         }
+                        optimisticOpts.log(method);
 
                         CiTargetMethod result = null;
                         TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
@@ -315,7 +316,8 @@
                             result = Debug.scope("Compiling", new Callable<CiTargetMethod>() {
                                 @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 {
@@ -330,9 +332,13 @@
                         compiler.getRuntime().installMethod(method, result);
                     } catch (CiBailout bailout) {
                         Debug.metric("Bailouts").increment();
-                        if (GraalOptions.ExitVMOnBailout) {
+                        if (GraalOptions.PrintBailouts || GraalOptions.ExitVMOnBailout) {
+                            TTY.println("WARN: Compilation bailout");
                             bailout.printStackTrace(TTY.cachedOut);
-                            System.exit(-1);
+
+                            if (GraalOptions.ExitVMOnBailout) {
+                                System.exit(-1);
+                            }
                         }
                     } catch (Throwable t) {
                         if (GraalOptions.ExitVMOnException) {
@@ -444,8 +450,10 @@
         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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodData.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotMethodResolvedImpl.java	Wed Mar 21 11:28:22 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 10:47:02 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotProfilingInfo.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java	Wed Mar 21 11:28:22 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)), StructuredGraph.INVALID_GRAPH_ID));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID));
             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)), StructuredGraph.INVALID_GRAPH_ID));
+            memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID));
             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)), StructuredGraph.INVALID_GRAPH_ID);
+                    GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID);
                     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)), StructuredGraph.INVALID_GRAPH_ID));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID));
             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)), StructuredGraph.INVALID_GRAPH_ID));
+            memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID));
             graph.replaceFixed(objectClassNode, memoryRead);
         }
     }
@@ -328,7 +328,7 @@
     }
 
     private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool, long leafGraphId) {
-        return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), leafGraphId);
+        return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length())), RiDeoptReason.BoundsCheckException, leafGraphId);
     }
 
     @Override
@@ -349,7 +349,7 @@
                 StructuredGraph graph = new StructuredGraph();
                 LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0));
                 SafeReadNode klassOop = safeReadHub(graph, receiver, StructuredGraph.INVALID_GRAPH_ID);
-                ReadNode result = graph.add(new ReadNode(klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), StampFactory.objectNonNull()));
+                FloatingReadNode result = graph.unique(new FloatingReadNode(klassOop, null, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph), StampFactory.objectNonNull()));
                 ReturnNode ret = graph.add(new ReturnNode(result));
                 graph.start().setNext(klassOop);
                 klassOop.setNext(ret);
@@ -424,13 +424,55 @@
     @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 long[] getDeoptedLeafGraphIds() {
         return compiler.getVMEntries().getDeoptedLeafGraphIds();
     }
+
+    @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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Wed Mar 21 11:28:22 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/FrameStateBuilder.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Wed Mar 21 11:28:22 2012 +0100
@@ -22,19 +22,19 @@
  */
 package com.oracle.graal.java;
 
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
 import static com.oracle.graal.nodes.ValueUtil.*;
 import static java.lang.reflect.Modifier.*;
 
 import java.util.*;
 
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ri.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
-import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
 
 public class FrameStateBuilder {
     private final RiResolvedMethod method;
@@ -169,7 +169,7 @@
 
         } else if (block.isPhiAtMerge(currentValue)) {
             if (otherValue == null || currentValue.kind() != otherValue.kind()) {
-                deletePhi(currentValue);
+                deletePhi((PhiNode) currentValue);
                 return null;
             }
             ((PhiNode) currentValue).addInput(otherValue);
@@ -194,19 +194,19 @@
         }
     }
 
-    private void deletePhi(Node phi) {
+    private void deletePhi(PhiNode phi) {
         if (phi.isDeleted()) {
             return;
         }
         // Collect all phi functions that use this phi so that we can delete them recursively (after we delete ourselfs to avoid circles).
-        List<Node> phiUsages = phi.usages().filter(NodePredicates.isA(PhiNode.class)).snapshot();
+        List<PhiNode> phiUsages = phi.usages().filter(PhiNode.class).snapshot();
 
         // Remove the phi function from all FrameStates where it is used and then delete it.
-        assert phi.usages().filter(NodePredicates.isNotA(FrameState.class)).filter(NodePredicates.isNotA(PhiNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
+        assert phi.usages().filter(isNotA(FrameState.class).nor(PhiNode.class)).isEmpty() : "phi function that gets deletes must only be used in frame states";
         phi.replaceAtUsages(null);
         phi.safeDelete();
 
-        for (Node phiUsage : phiUsages) {
+        for (PhiNode phiUsage : phiUsages) {
             deletePhi(phiUsage);
         }
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Mar 21 11:28:22 2012 +0100
@@ -29,11 +29,6 @@
 import java.util.*;
 import java.util.concurrent.atomic.*;
 
-
-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.*;
@@ -43,13 +38,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.
@@ -90,7 +88,8 @@
 
     private BitSet canTrapBitSet;
 
-    private final GraphBuilderConfiguration config;
+    private final GraphBuilderConfiguration graphBuilderConfig;
+    private final OptimisticOptimizations optimisticOpts;
 
     private long graphId;
 
@@ -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;
     }
@@ -130,7 +125,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();
     }
 
@@ -140,7 +135,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));
 
@@ -191,7 +186,7 @@
 
         connectLoopEndToBegin();
 
-        // remove Placeholders (except for loop exits)
+        // remove Placeholders
         for (BlockPlaceholderNode n : currentGraph.getNodes(BlockPlaceholderNode.class)) {
             currentGraph.removeFixed(n);
         }
@@ -252,7 +247,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;
@@ -325,7 +320,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, graphId)));
+                append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
                 frameState.push(CiKind.Object, append(ConstantNode.forObject(null, runtime, currentGraph)));
             }
         } else if (con instanceof CiConstant) {
@@ -584,7 +579,7 @@
 
     private void genThrow(int bci) {
         ValueNode exception = frameState.apop();
-        FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)), graphId));
+        FixedGuardNode node = currentGraph.add(new FixedGuardNode(currentGraph.unique(new NullCheckNode(exception, false)), RiDeoptReason.NullCheckException, graphId));
         append(node);
         append(handleException(exception, bci));
     }
@@ -592,39 +587,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);
         }
     }
@@ -632,7 +627,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();
@@ -676,7 +671,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))), graphId)));
+            append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(object, Condition.EQ, ConstantNode.forObject(null, runtime, currentGraph))), RiDeoptReason.Unresolved, graphId)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -694,7 +689,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, graphId));
+            DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId));
             IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new NullCheckNode(object, true)), trueSucc, deopt, 1));
             append(ifNode);
             lastInstr = trueSucc;
@@ -708,7 +703,7 @@
             NewInstanceNode n = currentGraph.add(new NewInstanceNode((RiResolvedType) type));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -749,7 +744,7 @@
             NewArrayNode n = currentGraph.add(new NewObjectArrayNode((RiResolvedType) type, length));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
 
@@ -766,7 +761,7 @@
             FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((RiResolvedType) type, dims));
             frameState.apush(append(n));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             frameState.apush(appendConstant(CiConstant.NULL_OBJECT));
         }
     }
@@ -780,7 +775,7 @@
             LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (RiResolvedField) field));
             appendOptimizedLoadField(kind, load);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             frameState.push(kind.stackKind(), append(ConstantNode.defaultForKind(kind, currentGraph)));
         }
     }
@@ -881,7 +876,7 @@
             StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (RiResolvedField) field, value));
             appendOptimizedStoreField(store);
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
         }
     }
 
@@ -923,7 +918,7 @@
         if (initialized) {
             return appendConstant(((RiResolvedType) holder).getEncoding(representation));
         } else {
-            append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)));
+            append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
             return null;
         }
     }
@@ -984,7 +979,7 @@
     }
 
     private void genInvokeDeopt(RiMethod unresolvedTarget, boolean withReceiver) {
-        append(currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, graphId)));
+        append(currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, RiDeoptReason.Unresolved, graphId)));
         frameState.popArguments(unresolvedTarget.signature().argumentSlots(withReceiver), unresolvedTarget.signature().argumentCount(withReceiver));
         CiKind kind = unresolvedTarget.signature().returnKind(false);
         if (kind != CiKind.Void) {
@@ -1021,7 +1016,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, StructuredGraph.INVALID_GRAPH_ID));
+            DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(RiDeoptAction.None, RiDeoptReason.RuntimeConstraint, StructuredGraph.INVALID_GRAPH_ID));
             deoptimize.setMessage("invoke " + targetMethod.name());
             append(deoptimize);
             frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph));
@@ -1110,7 +1105,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))), graphId)));
+        append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new CompareNode(local, Condition.EQ, ConstantNode.forJsr(retAddress, currentGraph))), RiDeoptReason.JavaSubroutineMismatch, graphId)));
         if (!successor.jsrScope.equals(scope.pop())) {
             throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
         }
@@ -1195,8 +1190,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, graphId));
+        if (probability == 0 && optimisticOpts.removeNeverExecutedCode()) {
+            return currentGraph.add(new DeoptimizeNode(RiDeoptAction.InvalidateReprofile, RiDeoptReason.UnreachedCode, graphId));
         } else {
             return createTarget(block, stateAfter);
         }
@@ -1337,7 +1332,7 @@
                 currentGraph.reduceDegenerateLoopBegin(begin);
             } else {
                 // Delete unnecessary loop phi functions, i.e., phi functions where all inputs are either the same or the phi itself.
-                for (PhiNode phi : begin.stateAfter().values().filter(PhiNode.class).snapshot()) {
+                for (PhiNode phi : begin.phis().snapshot()) {
                     checkRedundantPhi(phi);
                 }
             }
@@ -1400,13 +1395,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.jtt/src/com/oracle/graal/jtt/loop/LoopInline.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/loop/LoopInline.java	Wed Mar 21 11:28:22 2012 +0100
@@ -24,9 +24,6 @@
 
 import org.junit.*;
 
-/*
- * This test is meaningful only if you run it with 'forced' inlinning because running it in the harness with -Xcomp will not trigger any normal inlining
- */
 public class LoopInline {
 
     public static int test(int arg) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/CiLoweringTool.java	Wed Mar 21 11:28:22 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, long leafGraphId);
+    Node createGuard(Node condition, RiDeoptReason deoptReason, long leafGraphId);
 }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Mar 21 11:28:22 2012 +0100
@@ -25,29 +25,21 @@
 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 DeoptAction action;
+    @Data private final RiDeoptAction action;
+    @Data private final RiDeoptReason reason;
     private final long leafGraphId;
 
-    public DeoptimizeNode() {
-        this(DeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID);
-    }
 
-    public DeoptimizeNode(DeoptAction action, long leafGraphId) {
+    public DeoptimizeNode(RiDeoptAction action, RiDeoptReason reason, long leafGraphId) {
         super(StampFactory.illegal());
         this.action = action;
+        this.reason = reason;
         this.leafGraphId = leafGraphId;
     }
 
@@ -59,17 +51,21 @@
         return message;
     }
 
-    public DeoptAction action() {
+    public RiDeoptAction action() {
         return action;
     }
 
+    public RiDeoptReason reason() {
+        return reason;
+    }
+
     public long leafGraphId() {
         return leafGraphId;
     }
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimize(action, message, leafGraphId);
+        gen.emitDeoptimize(action, reason, message, leafGraphId);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Wed Mar 21 11:28:22 2012 +0100
@@ -24,25 +24,27 @@
 
 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;
     private final long leafGraphId;
 
-    public FixedGuardNode(BooleanNode condition, long leafGraphId) {
+    public FixedGuardNode(BooleanNode condition, RiDeoptReason deoptReason, long leafGraphId) {
         super(StampFactory.illegal());
         this.leafGraphId = leafGraphId;
         this.conditions = new NodeInputList<>(this, new BooleanNode[] {condition});
+        this.deoptReason = deoptReason;
     }
 
     @Override
     public void generate(LIRGeneratorTool gen) {
         for (BooleanNode condition : conditions()) {
-            gen.emitGuardCheck(condition, leafGraphId);
+            gen.emitGuardCheck(condition, deoptReason, leafGraphId);
         }
     }
 
@@ -66,7 +68,7 @@
                     if (next != null) {
                         tool.deleteBranch(next);
                     }
-                    setNext(graph().add(new DeoptimizeNode(DeoptAction.InvalidateRecompile, leafGraphId)));
+                    setNext(graph().add(new DeoptimizeNode(RiDeoptAction.InvalidateRecompile, deoptReason, leafGraphId)));
                     return;
                 }
             }
@@ -80,7 +82,7 @@
     public void lower(CiLoweringTool tool) {
         AnchorNode newAnchor = graph().add(new AnchorNode());
         for (BooleanNode b : conditions) {
-            newAnchor.addGuard((GuardNode) tool.createGuard(b, leafGraphId));
+            newAnchor.addGuard((GuardNode) tool.createGuard(b, deoptReason, leafGraphId));
         }
         ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Wed Mar 21 11:28:22 2012 +0100
@@ -209,7 +209,7 @@
             } else {
                 popSlots = 1;
             }
-            assert stackAt(stackSize() - popSlots).kind().stackKind() == popKind.stackKind();
+            assert stackAt(stackSize() - popSlots).kind().stackKind() == popKind.stackKind() || (stackAt(stackSize() - popSlots) instanceof BoxedVirtualObjectNode && popKind.isObject());
         }
 
         int pushSlots = pushedValues.length;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Mar 21 11:28:22 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;
     private final long leafGraphId;
 
     public FixedNode anchor() {
@@ -55,16 +57,21 @@
         condition = x;
     }
 
-    public GuardNode(BooleanNode condition, FixedNode anchor, long leafGraphId) {
+    public RiDeoptReason reason() {
+        return reason;
+    }
+
+    public GuardNode(BooleanNode condition, FixedNode anchor, RiDeoptReason reason, long leafGraphId) {
         super(StampFactory.illegal());
         this.condition = condition;
         this.anchor = anchor;
+        this.reason = reason;
         this.leafGraphId = leafGraphId;
     }
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitGuardCheck(condition(), leafGraphId);
+        gen.emitGuardCheck(condition(), reason(), leafGraphId);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 21 11:28:22 2012 +0100
@@ -185,6 +185,11 @@
         if (node == null) {
             assert kind() == CiKind.Void && usages().isEmpty();
             ((StructuredGraph) graph()).removeSplit(this, NORMAL_EDGE);
+        } else if (node instanceof DeoptimizeNode) {
+            this.replaceAtPredecessors(node);
+            this.replaceAtUsages(null);
+            GraphUtil.killCFG(this);
+            return;
         } else {
             ((StructuredGraph) graph()).replaceSplit(this, node, NORMAL_EDGE);
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeReadNode.java	Wed Mar 21 11:28:22 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)), StructuredGraph.INVALID_GRAPH_ID);
+        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID);
         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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SafeWriteNode.java	Wed Mar 21 11:28:22 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)), StructuredGraph.INVALID_GRAPH_ID);
+        GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)), RiDeoptReason.NullCheckException, StructuredGraph.INVALID_GRAPH_ID);
         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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Mar 21 11:28:22 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,13 +79,13 @@
 
     public abstract CiValue emitConvert(ConvertNode.Op opcode, CiValue inputVal);
     public abstract void emitMembar(int barriers);
-    public abstract void emitDeoptimizeOn(Condition cond, DeoptAction action, Object deoptInfo);
-    public abstract void emitDeoptimize(DeoptAction action, Object deoptInfo, long leafGraphId);
+    public abstract void emitDeoptimizeOn(Condition cond, RiDeoptAction action, RiDeoptReason reason, Object deoptInfo);
+    public abstract void emitDeoptimize(RiDeoptAction action, RiDeoptReason reason, Object deoptInfo, long leafGraphId);
     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, long leafGraphId);
+    public abstract void emitGuardCheck(BooleanNode comp, RiDeoptReason deoptReason, long leafGraphId);
 
     public abstract void emitLookupSwitch(LookupSwitchNode i);
     public abstract void emitTableSwitch(TableSwitchNode i);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Mar 21 11:28:22 2012 +0100
@@ -60,9 +60,8 @@
                 loopend.predecessor().replaceFirstSuccessor(loopend, null);
                 loopend.safeDelete();
             }
-            FixedNode next = begin.next();
+            killCFG(begin.next());
             begin.safeDelete();
-            killCFG(next);
         } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) { // not a loop anymore
             ((StructuredGraph) end.graph()).reduceDegenerateLoopBegin((LoopBeginNode) merge);
         } else if (merge.phiPredecessorCount() == 1) { // not a merge anymore
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java	Wed Mar 21 11:28:22 2012 +0100
@@ -297,6 +297,20 @@
                             assert false;
                     }
                     break;
+                case '\u0000': case '\u0001': case '\u0002': case '\u0003':
+                case '\u0004': case '\u0005': case '\u0006': case '\u0007':
+                case '\u0008': case '\u000b': case '\u000c': case '\u000e':
+                case '\u000f': case '\u0010': case '\u0011': case '\u0012':
+                case '\u0013': case '\u0014': case '\u0015': case '\u0016':
+                case '\u0017': case '\u0018': case '\u0019': case '\u001a':
+                case '\u001b': case '\u001c': case '\u001d': case '\u001e':
+                case '\u001f':
+                    if (str == null) {
+                        str = new StringBuilder();
+                        str.append(s, 0, i);
+                    }
+                    str.append("'0x").append(Integer.toHexString(c));
+                    break;
                 default:
                     if (str != null) {
                         str.append(c);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java	Wed Mar 21 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippets.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/BoxingEliminationTest.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/CompiledMethodTest.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/EscapeAnalysisTest.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphScheduleTest.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/GraphTest.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/IfBoxingEliminationTest.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeExceptionTest.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/InvokeTest.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/MonitorTest.java	Wed Mar 21 11:28:22 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 11:28:22 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 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiProfilingInfo.java	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ri/RiRuntime.java	Wed Mar 21 11:28:22 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 11:28:22 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/hotspot/.cproject	Wed Mar 21 10:47:02 2012 +0100
+++ b/hotspot/.cproject	Wed Mar 21 11:28:22 2012 +0100
@@ -20,7 +20,7 @@
 					<folderInfo id="cdt.managedbuild.toolchain.gnu.solaris.base.945602881.305678577" name="/" resourcePath="">
 						<toolChain id="cdt.managedbuild.toolchain.gnu.base.1866612258" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
 							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.2075405295" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
-							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build" autoBuildTarget="debug" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.81453037" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelizationNumber="1" superClass="cdt.managedbuild.target.gnu.builder.base">
+							<builder arguments="${workspace_loc:/hotspot}/../mxtool/mx build" autoBuildTarget="ide-build-target" buildPath="${workspace_loc:/hotspot}/.." cleanBuildTarget="clean" command="bash" enableAutoBuild="true" enableCleanBuild="false" enabledIncrementalBuild="false" id="cdt.managedbuild.target.gnu.builder.base.81453037" incrementalBuildTarget="jvmg1" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelizationNumber="1" superClass="cdt.managedbuild.target.gnu.builder.base">
 								<outputEntries>
 									<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
 								</outputEntries>
@@ -80,6 +80,7 @@
 			<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
 			<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
 			<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+			<storageModule moduleId="scannerConfiguration"/>
 		</cconfiguration>
 	</storageModule>
 	<storageModule moduleId="cdtBuildSystem" version="4.0.0">
--- a/hotspot/.project	Wed Mar 21 10:47:02 2012 +0100
+++ b/hotspot/.project	Wed Mar 21 11:28:22 2012 +0100
@@ -23,7 +23,7 @@
 				</dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
-					<value>debug</value>
+					<value>ide-build-target</value>
 				</dictionary>
 				<dictionary>
 					<key>org.eclipse.cdt.make.core.buildArguments</key>
--- a/mx/commands.py	Wed Mar 21 10:47:02 2012 +0100
+++ b/mx/commands.py	Wed Mar 21 11:28:22 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
     
@@ -414,6 +420,12 @@
         buildSuffix = 'graal'
         
     for build in builds:
+        if build == 'ide-build-target':
+            build = os.environ.get('IDE_BUILD_TARGET', 'product')
+            if len(build) == 0:
+                mx.log('[skipping build from IDE as IDE_BUILD_TARGET environment variable is ""]')
+                continue
+
         jdk = _jdk(build, create=True)
             
         vmDir = join(_vmLibDirInJdk(jdk), vm)
@@ -751,9 +763,19 @@
 def gv(args):
     """run the Graal Visualizer"""
     with open(join(_graal_home, '.graal_visualizer.log'), 'w') as fp:
-        mx.log('[Graal Visualizer output is in ' + fp.name + ']')
+        mx.log('[Graal Visualizer log is in ' + fp.name + ']')
+        if not exists(join(_graal_home, 'visualizer', 'build.xml')):
+            mx.log('[This initial execution may take a while as the NetBeans platform needs to be downloaded]')
         mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-l', fp.name, 'run'])
     
+def igv(args):
+    """run the Ideal Graph Visualizer"""
+    with open(join(_graal_home, '.ideal_graph_visualizer.log'), 'w') as fp:
+        mx.log('[Ideal Graph Visualizer log is in ' + fp.name + ']')
+        if not exists(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')):
+            mx.log('[This initial execution may take a while as the NetBeans platform needs to be downloaded]')
+        mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-l', fp.name, 'run'])
+
 def bench(args):
     """run benchmarks and parse their output for results
 
@@ -876,11 +898,13 @@
         'buildvms': [buildvms, '[-options]'],
         'clean': [clean, ''],
         '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]'],
-        'example': [example, '[-v] example names...'],
+        #'example': [example, '[-v] example names...'],
         'gate' : [gate, '[-options]'],
         'gv' : [gv, ''],
         'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
--- a/mxtool/mx.py	Wed Mar 21 10:47:02 2012 +0100
+++ b/mxtool/mx.py	Wed Mar 21 11:28:22 2012 +0100
@@ -510,6 +510,7 @@
         ArgumentParser.__init__(self, prog='mx')
 
         self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output')
+        self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output')
         self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on <port> for a debugger', metavar='<port>')
         self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"')
         self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='<arg>')
@@ -536,6 +537,9 @@
         opts.__dict__.setdefault('timeout', 0)
         opts.__dict__.setdefault('ptimeout', 0)
 
+        if opts.very_verbose:
+            opts.verbose = True
+
         if opts.java_home is None:
             opts.java_home = os.environ.get('JAVA_HOME')
 
@@ -640,6 +644,10 @@
         assert isinstance(arg, types.StringTypes), 'argument is not a string: ' + str(arg)
 
     if _opts.verbose:
+        if _opts.very_verbose:
+            log('Environment variables:')
+            for key in sorted(os.environ.keys()):
+                log('    ' + key + '=' + os.environ[key])
         log(' '.join(args))
 
     if timeout is None and _opts.ptimeout != 0:
@@ -697,7 +705,10 @@
 
     if retcode and nonZeroIsFatal:
         if _opts.verbose:
-            raise subprocess.CalledProcessError(retcode, ' '.join(args))
+            if _opts.very_verbose:
+                raise subprocess.CalledProcessError(retcode, ' '.join(args))
+            else:
+                log('[exit code: ' + str(retcode)+ ']')
         abort(retcode)
 
     return retcode
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Mar 21 10:47:02 2012 +0100
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Mar 21 11:28:22 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/tools/IdealGraphVisualizer/nbproject/platform.properties	Wed Mar 21 10:47:02 2012 +0100
+++ b/src/share/tools/IdealGraphVisualizer/nbproject/platform.properties	Wed Mar 21 11:28:22 2012 +0100
@@ -1,3 +1,11 @@
+nbplatform.active=default
+bootstrap.url=http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar
+autoupdate.catalog.url=http://updates.netbeans.org/netbeans/updates/7.1.1/uc/final/distribution/catalog.xml.gz
+suite.dir=${basedir}
+nbplatform.active.dir=${suite.dir}/nbplatform
+nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform
+nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness
+harness.dir=${nbplatform.active.dir}/harness
 cluster.path=\
     ${nbplatform.active.dir}/ide:\
     ${nbplatform.active.dir}/platform
@@ -201,4 +209,4 @@
 #   org.netbeans.core.netigso,\
 #   org.netbeans.libs.felix,\
 #   org.netbeans.libs.osgi,\
-nbplatform.active=default
+
--- a/src/share/vm/c1/c1_Runtime1.cpp	Wed Mar 21 10:47:02 2012 +0100
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/code/codeBlob.hpp	Wed Mar 21 11:28:22 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/code/nmethod.hpp	Wed Mar 21 10:47:02 2012 +0100
+++ b/src/share/vm/code/nmethod.hpp	Wed Mar 21 11:28:22 2012 +0100
@@ -596,7 +596,7 @@
 
   // (thomaswue) When using graal, the address might be off by 5 (because this is the size of the call instruction.
   // (thomaswue) TODO: Replace this by a more general mechanism.
-  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin() IS_GRAAL( || pc == deopt_handler_begin() + 5); }
+  bool is_deopt_entry   (address pc) { return pc == deopt_handler_begin() GRAAL_ONLY( || pc == deopt_handler_begin() + 5); }
   bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
   // Accessor/mutator for the original pc of a frame before a frame was deopted.
   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 21 10:47:02 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Wed Mar 21 11:28:22 2012 +0100
@@ -319,7 +319,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 10:47:02 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/oops/methodDataOop.hpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/oops/methodOop.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/opto/runtime.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/prims/jvmtiEnvBase.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/prims/jvmtiImpl.cpp	Wed Mar 21 11:28:22 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/arguments.cpp	Wed Mar 21 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Wed Mar 21 11:28:22 2012 +0100
@@ -2127,7 +2127,7 @@
     }
     if (PrintVMOptions) tty->print_cr("GRAAL=%s", graal_dir);
     
-    SysClassPath scp_compiler(Arguments::get_sysclasspath());
+    SysClassPath scp_compiler("");
     struct dirent* dentry;
     char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(graal_dir));
     errno = 0;
--- a/src/share/vm/runtime/compilationPolicy.hpp	Wed Mar 21 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/compilationPolicy.hpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Mar 21 11:28:22 2012 +0100
@@ -1151,17 +1151,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.
@@ -1173,12 +1173,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.
@@ -1187,15 +1187,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);
   }
 }
@@ -1520,7 +1520,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,
@@ -1654,25 +1654,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.
@@ -1717,8 +1723,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 = GRAAL_ONLY(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);
@@ -1831,6 +1840,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",
@@ -1849,6 +1873,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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/deoptimization.hpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/safepoint.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/thread.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/vm_operations.cpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/runtime/vm_operations.hpp	Wed Mar 21 11:28:22 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 10:47:02 2012 +0100
+++ b/src/share/vm/utilities/macros.hpp	Wed Mar 21 11:28:22 2012 +0100
@@ -75,9 +75,11 @@
 #endif // COMPILER2
 
 #ifdef GRAAL
-#define IS_GRAAL(code) code
+#define GRAAL_ONLY(code...) code
+#define NOT_GRAAL(code)
 #else
-#define IS_GRAAL(code)
+#define GRAAL_ONLY(code...)
+#define NOT_GRAAL(code) code
 #endif
 
 #ifdef TIERED
@@ -258,14 +260,6 @@
 #define NOT_EMBEDDED(code) code
 #endif
 
-#ifdef GRAAL
-#define GRAAL_ONLY(code...) code
-#define NOT_GRAAL(code...)
-#else
-#define GRAAL_ONLY(code...)
-#define NOT_GRAAL(code...) code
-#endif
-
 #define define_pd_global(type, name, value) const type pd_##name = value;
 
 #endif // SHARE_VM_UTILITIES_MACROS_HPP
--- a/src/share/vm/utilities/ostream.cpp	Wed Mar 21 10:47:02 2012 +0100
+++ b/src/share/vm/utilities/ostream.cpp	Wed Mar 21 11:28:22 2012 +0100
@@ -616,9 +616,9 @@
       // Print it as a java-style property list.
       // System properties don't generally contain newlines, so don't bother with unparsing.
       for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
-        xs->text()->print(p->key());
+        xs->text()->print(p->key() ? p->key() : "");
         xs->text()->print("=");
-        xs->text()->print_cr(p->value());
+        xs->text()->print_cr(p->value() ? p->value() : "");
       }
       xs->tail("properties");
     }