changeset 8217:dce9cefed571

Draft speculation log.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 11 Mar 2013 23:28:34 +0100
parents 169ec449974a
children b45ed2b14fd1
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java
diffstat 19 files changed, 148 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Mon Mar 11 23:28:34 2013 +0100
@@ -25,6 +25,8 @@
 import java.io.*;
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
+
 /**
  * Represents the debugging information for a particular place in the code, which includes the code
  * position, a reference map, and deoptimization information.
@@ -36,6 +38,7 @@
     private final BytecodePosition bytecodePosition;
     private final BitSet registerRefMap;
     private final BitSet frameRefMap;
+    private final short deoptimizationReason;
 
     /**
      * Creates a new {@link DebugInfo} from the given values.
@@ -45,10 +48,11 @@
      * @param registerRefMap the register map
      * @param frameRefMap the reference map for {@code frame}, which may be {@code null}
      */
-    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap) {
+    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, short deoptimizationReason) {
         this.bytecodePosition = codePos;
         this.registerRefMap = registerRefMap;
         this.frameRefMap = frameRefMap;
+        this.deoptimizationReason = deoptimizationReason;
     }
 
     /**
@@ -114,4 +118,13 @@
     public BitSet getFrameRefMap() {
         return frameRefMap;
     }
+
+    /**
+     * Identifies the reason in case a deoptimization happens at this program counter.
+     * 
+     * @return the reason of the deoptimization
+     */
+    public short getDeoptimizationReason() {
+        return deoptimizationReason;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Mon Mar 11 23:28:34 2013 +0100
@@ -0,0 +1,74 @@
+/*
+ * 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.api.code;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Manages a list of unique deoptimization reasons and returns a unique index for each reason. This
+ * class is not thread safe and assumes that at every point in time there is only a single Graal
+ * compilation accessing this object.
+ * 
+ */
+public final class SpeculationLog {
+
+    public static final int MAX_CACHE_SIZE = 1 << 15;
+
+    private List<DeoptimizationReason> speculations = new ArrayList<>();
+    private boolean[] map = new boolean[10];
+    private Set<DeoptimizationReason> snapshot = new HashSet<>();
+
+    public short addSpeculation(DeoptimizationReason reason) {
+        short index = (short) speculations.indexOf(reason);
+        if (index != -1) {
+            // Nothing to add, reason already registered.
+            return index;
+        }
+        if (speculations.size() >= MAX_CACHE_SIZE) {
+            throw new BailoutException("Too many deoptimization reasons recorded");
+        }
+        speculations.add(reason);
+        if (map.length < speculations.size()) {
+            map = Arrays.copyOf(map, map.length * 2);
+        }
+        return (short) (speculations.size() - 1);
+    }
+
+    public boolean[] getRawMap() {
+        return map;
+    }
+
+    public void snapshot() {
+        for (int i = 0; i < speculations.size(); ++i) {
+            if (map[i]) {
+                snapshot.add(speculations.get(i));
+            }
+        }
+    }
+
+    public boolean maySpeculate(DeoptimizationReason reason) {
+        return !snapshot.contains(reason);
+    }
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Mon Mar 11 23:28:34 2013 +0100
@@ -175,5 +175,4 @@
      * Returns the localvariable table of this method.
      */
     LocalVariableTable getLocalVariableTable();
-
 }
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Mar 11 23:28:34 2013 +0100
@@ -774,7 +774,7 @@
 
     @Override
     public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason) {
-        LIRFrameState info = state();
+        LIRFrameState info = state(reason);
         LabelRef stubEntry = createDeoptStub(action, reason, info);
         append(new BranchOp(ConditionFlag.Overflow, stubEntry, info));
     }
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Mon Mar 11 23:28:34 2013 +0100
@@ -71,7 +71,7 @@
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase());
         new PTXPhase().apply(graph);
-        CompilationResult result = GraalCompiler.compileMethod(runtime, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE);
+        CompilationResult result = GraalCompiler.compileMethod(runtime, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog());
         System.out.println("result=" + result);
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Mar 11 23:28:34 2013 +0100
@@ -360,7 +360,8 @@
                 GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
                 phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
                 editPhasePlan(method, graph, phasePlan);
-                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL);
+                CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL,
+                                new SpeculationLog());
                 if (printCompilation) {
                     TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
                 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Mon Mar 11 23:28:34 2013 +0100
@@ -115,7 +115,7 @@
 
             @Override
             public LIR call() {
-                return GraalCompiler.emitHIR(runtime, backend.target, graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE);
+                return GraalCompiler.emitHIR(runtime, backend.target, graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog());
             }
         });
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Mar 11 23:28:34 2013 +0100
@@ -48,7 +48,7 @@
 public class GraalCompiler {
 
     public static CompilationResult compileMethod(final GraalCodeCacheProvider runtime, final Backend backend, final TargetDescription target, final ResolvedJavaMethod method,
-                    final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) {
+                    final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
         assert (method.getModifiers() & Modifier.NATIVE) == 0 : "compiling native methods is not supported";
 
         return Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Callable<CompilationResult>() {
@@ -58,7 +58,7 @@
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
                     public LIR call() {
-                        return emitHIR(runtime, target, graph, assumptions, cache, plan, optimisticOpts);
+                        return emitHIR(runtime, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog);
                     }
                 });
                 final FrameMap frameMap = Debug.scope("BackEnd", lir, new Callable<FrameMap>() {
@@ -96,7 +96,11 @@
      * @param target
      */
     public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan,
-                    OptimisticOptimizations optimisticOpts) {
+                    OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
+
+        if (speculationLog != null) {
+            speculationLog.snapshot();
+        }
 
         if (graph.start().next() == null) {
             plan.runPhases(PhasePosition.AFTER_PARSING, graph);
@@ -216,7 +220,7 @@
                 List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
                 List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
 
-                LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder);
+                LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder, speculationLog);
                 Debug.dump(lir, "After linear scan order");
                 return lir;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Mon Mar 11 23:28:34 2013 +0100
@@ -45,7 +45,7 @@
     private HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>();
     private IdentityHashMap<VirtualObjectNode, EscapeObjectState> objectStates = new IdentityHashMap<>();
 
-    public LIRFrameState build(FrameState topState, List<StackSlot> lockData, LabelRef exceptionEdge) {
+    public LIRFrameState build(FrameState topState, List<StackSlot> lockData, short reason, LabelRef exceptionEdge) {
         assert virtualObjects.size() == 0;
         assert objectStates.size() == 0;
 
@@ -103,7 +103,7 @@
         }
         objectStates.clear();
 
-        return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge);
+        return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason);
     }
 
     private BytecodeFrame computeFrameForState(FrameState state, List<StackSlot> lockDataSlots) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Mar 11 23:28:34 2013 +0100
@@ -231,19 +231,23 @@
     }
 
     public LIRFrameState state() {
+        return state(null);
+    }
+
+    public LIRFrameState state(DeoptimizationReason reason) {
         assert lastState != null || needOnlyOopMaps() : "must have state before instruction";
-        return stateFor(lastState);
+        return stateFor(lastState, reason);
     }
 
-    public LIRFrameState stateFor(FrameState state) {
-        return stateFor(state, null);
+    public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) {
+        return stateForWithExceptionEdge(state, reason, null);
     }
 
-    public LIRFrameState stateFor(FrameState state, LabelRef exceptionEdge) {
+    public LIRFrameState stateForWithExceptionEdge(FrameState state, DeoptimizationReason reason, LabelRef exceptionEdge) {
         if (needOnlyOopMaps()) {
-            return new LIRFrameState(null, null, null);
+            return new LIRFrameState(null, null, null, (short) -1);
         }
-        return debugInfoBuilder.build(state, lockDataSlots.subList(0, currentLockCount), exceptionEdge);
+        return debugInfoBuilder.build(state, lockDataSlots.subList(0, currentLockCount), lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge);
     }
 
     /**
@@ -595,7 +599,7 @@
             // False constants are handled within emitBranch.
         } else {
             // Fall back to a normal branch.
-            LIRFrameState info = state();
+            LIRFrameState info = state(deoptReason);
             LabelRef stubEntry = createDeoptStub(action, deoptReason, info);
             if (negated) {
                 emitBranch(comp, stubEntry, null, info);
@@ -716,7 +720,7 @@
 
         LIRFrameState callState = null;
         if (x.stateAfter() != null) {
-            callState = stateFor(x.stateDuring(), x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null);
+            callState = stateForWithExceptionEdge(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null);
         }
 
         Value result = cc.getReturn();
@@ -818,7 +822,7 @@
             if ((stateAfter.stackSize() > 0 && stateAfter.stackAt(stateAfter.stackSize() - 1) == x) || (stateAfter.stackSize() > 1 && stateAfter.stackAt(stateAfter.stackSize() - 2) == x)) {
                 stateBeforeReturn = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), x.kind());
             }
-            info = stateFor(stateBeforeReturn);
+            info = stateFor(stateBeforeReturn, null);
         } else {
             info = state();
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Mar 11 23:28:34 2013 +0100
@@ -185,7 +185,7 @@
 
         @Override
         public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
-            append(new AMD64DeoptimizeOp(action, reason, state()));
+            append(new AMD64DeoptimizeOp(action, reason, state(reason)));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Mon Mar 11 23:28:34 2013 +0100
@@ -146,7 +146,8 @@
                             graph = graph.copy();
                         }
                         InlinedBytecodes.add(method.getCodeSize());
-                        return GraalCompiler.compileMethod(graalRuntime.getRuntime(), graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan, optimisticOpts);
+                        return GraalCompiler.compileMethod(graalRuntime.getRuntime(), graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan,
+                                        optimisticOpts, method.getSpeculationLog());
                     }
                 });
             } finally {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Mar 11 23:28:34 2013 +0100
@@ -25,6 +25,7 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -152,7 +153,7 @@
      *            not null
      * @return the outcome of the installation as a {@link CodeInstallResult}.
      */
-    CodeInstallResult installCode(HotSpotCompilationResult compResult, HotSpotInstalledCode code, HotSpotCodeInfo info, boolean[] triggeredDeoptimizations);
+    CodeInstallResult installCode(HotSpotCompilationResult compResult, HotSpotInstalledCode code, HotSpotCodeInfo info, SpeculationLog cache);
 
     void initializeConfiguration(HotSpotVMConfig config);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Mar 11 23:28:34 2013 +0100
@@ -25,6 +25,7 @@
 
 import java.lang.reflect.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -37,8 +38,8 @@
     private native int installCode0(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info, boolean[] triggeredDeoptimizations);
 
     @Override
-    public CodeInstallResult installCode(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info, boolean[] triggeredDeoptimizations) {
-        return CodeInstallResult.values()[installCode0(comp, code, info, triggeredDeoptimizations)];
+    public CodeInstallResult installCode(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info, SpeculationLog speculationLog) {
+        return CodeInstallResult.values()[installCode0(comp, code, info, (speculationLog == null) ? null : speculationLog.getRawMap())];
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Mon Mar 11 23:28:34 2013 +0100
@@ -30,6 +30,7 @@
 import java.util.*;
 import java.util.concurrent.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ProfilingInfo.ExceptionSeen;
 import com.oracle.graal.bytecode.*;
@@ -58,8 +59,8 @@
     private HotSpotMethodData methodData;
     private byte[] code;
     private int compilationComplexity;
-
     private CompilationTask currentTask;
+    private SpeculationLog speculationLog;
 
     HotSpotResolvedJavaMethod(HotSpotResolvedObjectType holder, long metaspaceMethod) {
         this.metaspaceMethod = metaspaceMethod;
@@ -345,4 +346,10 @@
         return currentTask;
     }
 
+    public SpeculationLog getSpeculationLog() {
+        if (speculationLog == null) {
+            speculationLog = new SpeculationLog();
+        }
+        return speculationLog;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Mar 11 23:28:34 2013 +0100
@@ -818,7 +818,7 @@
     public void installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult, CodeInfo[] info) {
         HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info);
         HotSpotInstalledCode code = new HotSpotInstalledCode(method, true);
-        graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), code, hsInfo, null);
+        graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), code, hsInfo, method.getSpeculationLog());
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Mar 11 23:28:34 2013 +0100
@@ -118,7 +118,8 @@
         PhasePlan phasePlan = new PhasePlan();
         GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-        final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL);
+        final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL,
+                        new SpeculationLog());
 
         final CodeInfo[] info = new CodeInfo[1];
         stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable<InstalledCode>() {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Mon Mar 11 23:28:34 2013 +0100
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
@@ -74,6 +75,8 @@
 
     private boolean hasArgInCallerFrame;
 
+    private final SpeculationLog speculationLog;
+
     /**
      * An opaque chunk of machine code.
      */
@@ -90,7 +93,7 @@
     /**
      * Creates a new LIR instance for the specified compilation.
      */
-    public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder) {
+    public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder, SpeculationLog speculationLog) {
         this.cfg = cfg;
         this.blockToNodesMap = blockToNodesMap;
         this.codeEmittingOrder = codeEmittingOrder;
@@ -98,6 +101,11 @@
         this.lirInstructions = new BlockMap<>(cfg);
 
         stubs = new ArrayList<>();
+        this.speculationLog = speculationLog;
+    }
+
+    public SpeculationLog getDeoptimizationReasons() {
+        return speculationLog;
     }
 
     /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Mon Mar 11 20:55:31 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Mon Mar 11 23:28:34 2013 +0100
@@ -42,11 +42,13 @@
     private final VirtualObject[] virtualObjects;
     public final LabelRef exceptionEdge;
     private DebugInfo debugInfo;
+    private final short deoptimizationReason;
 
-    public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) {
+    public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge, short deoptimizationReason) {
         this.topFrame = topFrame;
         this.virtualObjects = virtualObjects;
         this.exceptionEdge = exceptionEdge;
+        this.deoptimizationReason = deoptimizationReason;
     }
 
     public boolean hasDebugInfo() {
@@ -111,7 +113,7 @@
     }
 
     public void finish(BitSet registerRefMap, BitSet frameRefMap) {
-        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap);
+        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap, deoptimizationReason);
     }
 
     @Override