changeset 13641:5a9afbf72714

Add a speculation oop for uncommon trap deoptimization. Save it in the SpeculationLog during deoptimization.
author Gilles Duboscq <duboscq@ssw.jku.at>
date Thu, 12 Dec 2013 15:13:02 +0100
parents bfe7a8c8c3c6
children 10f943c778f6
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.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/HotSpotMetaAccessProvider.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/code/nmethod.cpp src/share/vm/code/nmethod.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCodeInstaller.hpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalEnv.cpp src/share/vm/graal/graalEnv.hpp src/share/vm/graal/graalJavaAccess.hpp src/share/vm/graal/vmStructs_graal.hpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/deoptimization.hpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/vmStructs.cpp src/share/vm/utilities/exceptions.hpp
diffstat 36 files changed, 166 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Thu Dec 12 15:13:02 2013 +0100
@@ -27,51 +27,27 @@
 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.
+ * Manages a list of unique deoptimization reasons.
  * 
  */
 public final class SpeculationLog {
-
-    public static final int MAX_CACHE_SIZE = 1 << 15;
-
-    private List<Object> speculations = new ArrayList<>();
-    private boolean[] map = new boolean[10];
-    private Set<Object> snapshot = new HashSet<>();
+    private Set<Object> failedSpeculations;
+    private Object lastFailed;
 
-    private short addSpeculation(Object 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 synchronized void collectFailedSpeculations() {
+        if (lastFailed != null) {
+            if (failedSpeculations == null) {
+                failedSpeculations = new HashSet<>(2);
             }
+            failedSpeculations.add(lastFailed);
+            lastFailed = null;
         }
     }
 
     public Constant maySpeculate(Object reason) {
-        if (snapshot.contains(reason)) {
+        if (failedSpeculations != null && failedSpeculations.contains(reason)) {
             return null;
         }
-        return Constant.forShort(addSpeculation(reason));
+        return Constant.forObject(reason);
     }
 }
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Thu Dec 12 15:13:02 2013 +0100
@@ -607,7 +607,7 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Thu Dec 12 15:13:02 2013 +0100
@@ -696,7 +696,7 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Dec 12 15:13:02 2013 +0100
@@ -922,7 +922,7 @@
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Thu Dec 12 15:13:02 2013 +0100
@@ -192,7 +192,7 @@
                     OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites) {
 
         if (speculationLog != null) {
-            speculationLog.snapshot();
+            speculationLog.collectFailedSpeculations();
         }
 
         HighTierContext highTierContext = new HighTierContext(providers, assumptions, cache, graphBuilderSuite, optimisticOpts);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Dec 12 15:13:02 2013 +0100
@@ -386,29 +386,33 @@
         append(new AMD64HotSpotUnwindOp(exceptionParameter));
     }
 
-    private void moveDeoptimizationActionAndReasonToThread(Value actionAndReason) {
-        int pendingDeoptimizationOffset = runtime().getConfig().pendingDeoptimizationOffset;
+    private void moveDeoptValuesToThread(Value actionAndReason, Value speculation) {
+        moveValueToThread(actionAndReason, runtime().getConfig().pendingDeoptimizationOffset);
+        moveValueToThread(speculation, runtime().getConfig().pendingFailedSpeculationOffset);
+    }
+
+    private void moveValueToThread(Value v, int offset) {
         Kind wordKind = getProviders().getCodeCache().getTarget().wordKind;
         RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind);
-        AMD64AddressValue pendingDeoptAddress = new AMD64AddressValue(actionAndReason.getKind(), thread, pendingDeoptimizationOffset);
-        if (actionAndReason instanceof Constant && !getCodeCache().needsDataPatch((Constant) actionAndReason)) {
-            Constant constantActionAndReason = (Constant) actionAndReason;
+        AMD64AddressValue pendingDeoptAddress = new AMD64AddressValue(v.getKind(), thread, offset);
+        if (v instanceof Constant && !getCodeCache().needsDataPatch((Constant) v)) {
+            Constant constantActionAndReason = (Constant) v;
             assert !getCodeCache().needsDataPatch(constantActionAndReason);
             append(new StoreConstantOp(constantActionAndReason.getKind(), pendingDeoptAddress, constantActionAndReason, null));
         } else {
-            append(new StoreOp(actionAndReason.getKind(), pendingDeoptAddress, load(actionAndReason), null));
+            append(new StoreOp(v.getKind(), pendingDeoptAddress, load(v), null));
         }
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
-        moveDeoptimizationActionAndReasonToThread(actionAndReason);
+    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
+        moveDeoptValuesToThread(actionAndReason, speculation);
         append(new AMD64DeoptimizeOp(state(deopting)));
     }
 
     @Override
     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        moveDeoptimizationActionAndReasonToThread(getMetaAccess().encodeDeoptActionAndReason(action, reason, 0));
+        moveDeoptValuesToThread(getMetaAccess().encodeDeoptActionAndReason(action, reason, 0), Constant.NULL_OBJECT);
         append(new AMD64HotSpotDeoptimizeCallerOp());
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Dec 12 15:13:02 2013 +0100
@@ -192,23 +192,27 @@
         append(new SPARCHotSpotUnwindOp(exceptionParameter));
     }
 
-    private void moveDeoptimizationActionAndReasonToThread(Value actionAndReason) {
-        int pendingDeoptimizationOffset = runtime().getConfig().pendingDeoptimizationOffset;
+    private void moveDeoptValuesToThread(Value actionAndReason, Value speculation) {
+        moveValueToThread(actionAndReason, runtime().getConfig().pendingDeoptimizationOffset);
+        moveValueToThread(speculation, runtime().getConfig().pendingFailedSpeculationOffset);
+    }
+
+    private void moveValueToThread(Value v, int offset) {
         Kind wordKind = getProviders().getCodeCache().getTarget().wordKind;
         RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind);
-        SPARCAddressValue pendingDeoptAddress = new SPARCAddressValue(actionAndReason.getKind(), thread, pendingDeoptimizationOffset);
-        append(new StoreOp(actionAndReason.getKind(), pendingDeoptAddress, emitMove(actionAndReason), null));
+        SPARCAddressValue pendingDeoptAddress = new SPARCAddressValue(v.getKind(), thread, offset);
+        append(new StoreOp(v.getKind(), pendingDeoptAddress, emitMove(v), null));
     }
 
     @Override
-    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
-        moveDeoptimizationActionAndReasonToThread(actionAndReason);
+    public void emitDeoptimize(Value actionAndReason, Value speculation, DeoptimizingNode deopting) {
+        moveDeoptValuesToThread(actionAndReason, speculation);
         append(new SPARCDeoptimizeOp(state(deopting)));
     }
 
     @Override
     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        moveDeoptimizationActionAndReasonToThread(getMetaAccess().encodeDeoptActionAndReason(action, reason, 0));
+        moveDeoptValuesToThread(getMetaAccess().encodeDeoptActionAndReason(action, reason, 0), Constant.NULL_OBJECT);
         append(new SPARCHotSpotDeoptimizeCallerOp());
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Dec 12 15:13:02 2013 +0100
@@ -915,6 +915,7 @@
      */
     @HotSpotVMField(name = "ThreadShadow::_pending_exception", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingExceptionOffset;
     @HotSpotVMField(name = "ThreadShadow::_pending_deoptimization", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingDeoptimizationOffset;
+    @HotSpotVMField(name = "ThreadShadow::_pending_failed_speculation", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int pendingFailedSpeculationOffset;
 
     /**
      * Mark word right shift to get identity hash code.
@@ -1291,10 +1292,10 @@
 
     @HotSpotVMConstant(name = "Deoptimization::_action_bits") @Stable public int deoptimizationActionBits;
     @HotSpotVMConstant(name = "Deoptimization::_reason_bits") @Stable public int deoptimizationReasonBits;
-    @HotSpotVMConstant(name = "Deoptimization::_speculation_id_bits") @Stable public int deoptimizationSpeculationIdBits;
+    @HotSpotVMConstant(name = "Deoptimization::_debug_id_bits") @Stable public int deoptimizationDebugIdBits;
     @HotSpotVMConstant(name = "Deoptimization::_action_shift") @Stable public int deoptimizationActionShift;
     @HotSpotVMConstant(name = "Deoptimization::_reason_shift") @Stable public int deoptimizationReasonShift;
-    @HotSpotVMConstant(name = "Deoptimization::_speculation_id_shift") @Stable public int deoptimizationSpeculationIdShift;
+    @HotSpotVMConstant(name = "Deoptimization::_debug_id_shift") @Stable public int deoptimizationDebugIdShift;
 
     @HotSpotVMConstant(name = "vmIntrinsics::_invokeBasic") @Stable public int vmIntrinsicInvokeBasic;
     @HotSpotVMConstant(name = "vmIntrinsics::_linkToVirtual") @Stable public int vmIntrinsicLinkToVirtual;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Thu Dec 12 15:13:02 2013 +0100
@@ -33,11 +33,11 @@
  */
 public class CompilerToVMImpl implements CompilerToVM {
 
-    private native int installCode0(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, boolean[] triggeredDeoptimizations);
+    private native int installCode0(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog);
 
     @Override
     public CodeInstallResult installCode(HotSpotCompiledCode compiledCode, HotSpotInstalledCode code, SpeculationLog speculationLog) {
-        return CodeInstallResult.getEnum(installCode0(compiledCode, code, (speculationLog == null) ? null : speculationLog.getRawMap()));
+        return CodeInstallResult.getEnum(installCode0(compiledCode, code, speculationLog));
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Thu Dec 12 15:13:02 2013 +0100
@@ -134,8 +134,8 @@
         HotSpotVMConfig config = runtime.getConfig();
         int actionValue = convertDeoptAction(action);
         int reasonValue = convertDeoptReason(reason);
-        int speculationValue = speculationId & intMaskRight(config.deoptimizationSpeculationIdBits);
-        Constant c = Constant.forInt(~((speculationValue << config.deoptimizationSpeculationIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift)));
+        int speculationValue = speculationId & intMaskRight(config.deoptimizationDebugIdBits);
+        Constant c = Constant.forInt(~((speculationValue << config.deoptimizationDebugIdShift) | (reasonValue << config.deoptimizationReasonShift) | (actionValue << config.deoptimizationActionShift)));
         assert c.asInt() < 0;
         return c;
     }
@@ -156,7 +156,7 @@
 
     public short decodeSpeculationId(Constant constant) {
         HotSpotVMConfig config = runtime.getConfig();
-        return (short) (((~constant.asInt()) >> config.deoptimizationSpeculationIdShift) & intMaskRight(config.deoptimizationSpeculationIdBits));
+        return (short) (((~constant.asInt()) >> config.deoptimizationDebugIdShift) & intMaskRight(config.deoptimizationDebugIdBits));
     }
 
     public int convertDeoptAction(DeoptimizationAction action) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Thu Dec 12 15:13:02 2013 +0100
@@ -155,7 +155,8 @@
             }
             cond = graph.unique(new IntegerLessThanNode(end, v1));
         }
-        overflowGuard = graph.unique(new GuardNode(cond, BeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true));
+        overflowGuard = graph.unique(new GuardNode(cond, BeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
+                        Constant.NULL_OBJECT)); // TODO gd: use speculation
         loop.loopBegin().setOverflowGuard(overflowGuard);
         return overflowGuard;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Thu Dec 12 15:13:02 2013 +0100
@@ -63,4 +63,6 @@
     }
 
     public abstract ValueNode getActionAndReason(MetaAccessProvider metaAccess);
+
+    public abstract ValueNode getSpeculation(MetaAccessProvider metaAccess);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Thu Dec 12 15:13:02 2013 +0100
@@ -31,18 +31,21 @@
 
     private final DeoptimizationAction action;
     private final DeoptimizationReason reason;
-    private final int speculationId;
+    private final int debugId;
+    private final Constant speculation;
 
     public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) {
-        this(action, reason, 0);
+        this(action, reason, 0, Constant.NULL_OBJECT);
     }
 
-    public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int speculationId) {
+    public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason, int debugId, Constant speculation) {
         assert action != null;
         assert reason != null;
+        assert speculation.getKind() == Kind.Object;
         this.action = action;
         this.reason = reason;
-        this.speculationId = speculationId;
+        this.debugId = debugId;
+        this.speculation = speculation;
     }
 
     public DeoptimizationAction action() {
@@ -60,12 +63,17 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimize(gen.getMetaAccess().encodeDeoptActionAndReason(action, reason, speculationId), this);
+        gen.emitDeoptimize(gen.getMetaAccess().encodeDeoptActionAndReason(action, reason, debugId), speculation, this);
     }
 
     @Override
     public ValueNode getActionAndReason(MetaAccessProvider metaAccess) {
-        return ConstantNode.forConstant(metaAccess.encodeDeoptActionAndReason(action, reason, speculationId), metaAccess, graph());
+        return ConstantNode.forConstant(metaAccess.encodeDeoptActionAndReason(action, reason, debugId), metaAccess, graph());
+    }
+
+    @Override
+    public ValueNode getSpeculation(MetaAccessProvider metaAccess) {
+        return ConstantNode.forConstant(speculation, metaAccess, graph());
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java	Thu Dec 12 15:13:02 2013 +0100
@@ -29,22 +29,33 @@
 
 public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Canonicalizable {
     @Input private ValueNode actionAndReason;
+    @Input private ValueNode speculation;
 
-    public DynamicDeoptimizeNode(ValueNode actionAndReason) {
+    public DynamicDeoptimizeNode(ValueNode actionAndReason, ValueNode speculation) {
         this.actionAndReason = actionAndReason;
+        this.speculation = speculation;
     }
 
     public ValueNode getActionAndReason() {
         return actionAndReason;
     }
 
+    public ValueNode getSpeculation() {
+        return speculation;
+    }
+
     @Override
     public ValueNode getActionAndReason(MetaAccessProvider metaAccess) {
         return getActionAndReason();
     }
 
+    @Override
+    public ValueNode getSpeculation(MetaAccessProvider metaAccess) {
+        return getSpeculation();
+    }
+
     public void generate(LIRGeneratorTool generator) {
-        generator.emitDeoptimize(generator.operand(actionAndReason), this);
+        generator.emitDeoptimize(generator.operand(actionAndReason), generator.operand(speculation), this);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Thu Dec 12 15:13:02 2013 +0100
@@ -45,15 +45,17 @@
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
+    private final Constant speculation;
     private DeoptimizationAction action;
     private boolean negated;
 
-    public GuardNode(LogicNode condition, GuardingNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated) {
+    public GuardNode(LogicNode condition, GuardingNode anchor, DeoptimizationReason reason, DeoptimizationAction action, boolean negated, Constant speculation) {
         super(StampFactory.dependency(), anchor);
         this.condition = condition;
         this.reason = reason;
         this.action = action;
         this.negated = negated;
+        this.speculation = speculation;
     }
 
     /**
@@ -80,6 +82,10 @@
         return action;
     }
 
+    public Constant getSpeculation() {
+        return speculation;
+    }
+
     @Override
     public String toString(Verbosity verbosity) {
         if (verbosity == Verbosity.Name && negated) {
@@ -93,7 +99,7 @@
     public Node canonical(CanonicalizerTool tool) {
         if (condition() instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition();
-            return graph().unique(new GuardNode(negation.getInput(), getGuard(), reason, action, !negated));
+            return graph().unique(new GuardNode(negation.getInput(), getGuard(), reason, action, !negated, speculation));
         }
         if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Thu Dec 12 15:13:02 2013 +0100
@@ -69,7 +69,7 @@
 
     void emitMembar(int barriers);
 
-    void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting);
+    void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting);
 
     void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Thu Dec 12 15:13:02 2013 +0100
@@ -41,7 +41,8 @@
         ControlFlowGraph cfg = null;
         for (FrameState fs : graph.getNodes(FrameState.class)) {
             FixedNode target = null;
-            PhiNode phi = null;
+            PhiNode reasonActionPhi = null;
+            PhiNode speculationPhi = null;
             List<AbstractDeoptimizeNode> obsoletes = null;
             for (AbstractDeoptimizeNode deopt : fs.usages().filter(AbstractDeoptimizeNode.class)) {
                 if (target == null) {
@@ -54,14 +55,16 @@
                     if (target instanceof AbstractDeoptimizeNode) {
                         merge = graph.add(new MergeNode());
                         EndNode firstEnd = graph.add(new EndNode());
-                        phi = graph.addWithoutUnique(new PhiNode(Kind.Int, merge));
+                        reasonActionPhi = graph.addWithoutUnique(new PhiNode(Kind.Int, merge));
+                        speculationPhi = graph.addWithoutUnique(new PhiNode(Kind.Object, merge));
                         merge.addForwardEnd(firstEnd);
-                        phi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess()));
+                        reasonActionPhi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess()));
+                        speculationPhi.addInput(((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess()));
                         target.predecessor().replaceFirstSuccessor(target, firstEnd);
 
                         exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg);
 
-                        merge.setNext(graph.add(new DynamicDeoptimizeNode(phi)));
+                        merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi)));
                         obsoletes = new LinkedList<>();
                         obsoletes.add((AbstractDeoptimizeNode) target);
                         target = merge;
@@ -70,7 +73,8 @@
                     }
                     EndNode newEnd = graph.add(new EndNode());
                     merge.addForwardEnd(newEnd);
-                    phi.addInput(deopt.getActionAndReason(context.getMetaAccess()));
+                    reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess()));
+                    speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess()));
                     deopt.predecessor().replaceFirstSuccessor(deopt, newEnd);
                     exitLoops(deopt, newEnd, cfg);
                     obsoletes.add(deopt);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Thu Dec 12 15:13:02 2013 +0100
@@ -125,11 +125,11 @@
     private static class LowerGuards extends ScheduledNodeIterator {
 
         private final Block block;
-        private boolean useGuardIdAsSpeculationId;
+        private boolean useGuardIdAsDebugId;
 
-        public LowerGuards(Block block, boolean useGuardIdAsSpeculationId) {
+        public LowerGuards(Block block, boolean useGuardIdAsDebugId) {
             this.block = block;
-            this.useGuardIdAsSpeculationId = useGuardIdAsSpeculationId;
+            this.useGuardIdAsDebugId = useGuardIdAsDebugId;
         }
 
         @Override
@@ -149,7 +149,7 @@
             StructuredGraph graph = guard.graph();
             AbstractBeginNode fastPath = graph.add(new BeginNode());
             @SuppressWarnings("deprecation")
-            DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsSpeculationId ? guard.getId() : 0));
+            DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), useGuardIdAsDebugId ? guard.getId() : 0, guard.getSpeculation()));
             AbstractBeginNode deoptBranch = AbstractBeginNode.begin(deopt);
             AbstractBeginNode trueSuccessor;
             AbstractBeginNode falseSuccessor;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Thu Dec 12 15:13:02 2013 +0100
@@ -143,7 +143,7 @@
                 fixedGuard.lower(this);
                 return handle.getGuard();
             } else {
-                GuardNode newGuard = graph.unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated));
+                GuardNode newGuard = graph.unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, Constant.NULL_OBJECT));
                 if (OptEliminateGuards.getValue()) {
                     activeGuards.grow();
                     activeGuards.mark(newGuard);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java	Wed Jan 15 15:11:47 2014 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java	Thu Dec 12 15:13:02 2013 +0100
@@ -103,7 +103,7 @@
 
             if (otherGuards.size() == successorCount - 1) {
                 AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit));
-                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated()));
+                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated(), guard.getSpeculation()));
                 for (GuardNode otherGuard : otherGuards) {
                     otherGuard.replaceAndDelete(newGuard);
                 }
@@ -115,7 +115,8 @@
     }
 
     private static boolean compatibleGuards(GuardNode guard, GuardNode conditonGuard) {
-        return conditonGuard.negated() == guard.negated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason();
+        return conditonGuard.negated() == guard.negated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason() &&
+                        conditonGuard.getSpeculation().equals(guard.getSpeculation());
     }
 
     private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -227,6 +227,7 @@
   do_klass(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Opt) \
   do_klass(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Opt) \
   do_klass(VirtualObject_klass,                   com_oracle_graal_api_code_VirtualObject,                      Opt) \
+  do_klass(SpeculationLog_klass,                  com_oracle_graal_api_code_SpeculationLog,                     Opt) \
   /* graal.api.meta */                                                                                               \
   do_klass(Constant_klass,                        com_oracle_graal_api_meta_Constant,                           Opt) \
   do_klass(ExceptionHandler_klass,                com_oracle_graal_api_meta_ExceptionHandler,                   Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -348,6 +348,7 @@
   template(com_oracle_graal_api_code_VirtualObject,                  "com/oracle/graal/api/code/VirtualObject")                       \
   template(com_oracle_graal_api_code_RegisterSaveLayout,             "com/oracle/graal/api/code/RegisterSaveLayout")                  \
   template(com_oracle_graal_api_code_InvalidInstalledCodeException,  "com/oracle/graal/api/code/InvalidInstalledCodeException")       \
+  template(com_oracle_graal_api_code_SpeculationLog,                 "com/oracle/graal/api/code/SpeculationLog")                      \
   /* graal.truffle */                                                                                                                 \
   template(com_oracle_graal_truffle_GraalTruffleRuntime,             "com/oracle/graal/truffle/GraalTruffleRuntime")                  \
   template(startCompiler_name,                    "startCompiler")                                                                    \
--- a/src/share/vm/code/nmethod.cpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/code/nmethod.cpp	Thu Dec 12 15:13:02 2013 +0100
@@ -528,7 +528,7 @@
   _compiler                = NULL;
 #ifdef GRAAL
   _graal_installed_code   = NULL;
-  _triggered_deoptimizations = NULL;
+  _speculation_log        = NULL;
 #endif
 #ifdef HAVE_DTRACE_H
   _trap_offset             = 0;
@@ -627,7 +627,7 @@
   GrowableArray<jlong>* leaf_graph_ids
 #ifdef GRAAL
   , Handle installed_code,
-  Handle triggered_deoptimizations
+  Handle speculationLog
 #endif
 )
 {
@@ -656,7 +656,7 @@
             leaf_graph_ids
 #ifdef GRAAL
             , installed_code,
-            triggered_deoptimizations
+            speculationLog
 #endif
             );
 
@@ -885,7 +885,7 @@
   GrowableArray<jlong>* leaf_graph_ids
 #ifdef GRAAL
   , Handle installed_code,
-  Handle triggered_deoptimizations
+  Handle speculation_log
 #endif
   )
   : CodeBlob("nmethod", code_buffer, sizeof(nmethod),
@@ -913,7 +913,7 @@
 
 #ifdef GRAAL
     _graal_installed_code = installed_code();
-    _triggered_deoptimizations = (typeArrayOop)triggered_deoptimizations();
+    _speculation_log = (instanceOop)speculation_log();
 #endif
     if (compiler->is_graal()) {
       // Graal might not produce any stub sections
@@ -1762,6 +1762,12 @@
       }
     }
   }
+
+  if (_speculation_log != NULL) {
+    if (!is_alive->do_object_b(_speculation_log)) {
+      _speculation_log = NULL;
+    }
+  }
 #endif
 
   // Exception cache
@@ -1990,8 +1996,8 @@
   if (_graal_installed_code != NULL) {
     f->do_oop((oop*) &_graal_installed_code);
   }
-  if (_triggered_deoptimizations != NULL) {
-    f->do_oop((oop*) &_triggered_deoptimizations);
+  if (_speculation_log != NULL) {
+    f->do_oop((oop*) &_speculation_log);
   }
 #endif
 
--- a/src/share/vm/code/nmethod.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/code/nmethod.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -119,7 +119,7 @@
 #ifdef GRAAL
   // Needed to keep nmethods alive that are not the default nmethod for the associated Method.
   oop       _graal_installed_code;
-  typeArrayOop _triggered_deoptimizations;
+  oop       _speculation_log;
 #endif
 
   // To support simple linked-list chaining of nmethods:
@@ -280,7 +280,7 @@
           GrowableArray<jlong>* leaf_graph_ids
 #ifdef GRAAL
           , Handle installed_code,
-          Handle triggered_deoptimizations
+          Handle speculation_log
 #endif
           );
 
@@ -322,7 +322,7 @@
                               GrowableArray<jlong>* leaf_graph_ids = NULL
 #ifdef GRAAL
                               , Handle installed_code = Handle(),
-                              Handle triggered_deoptimizations = Handle()
+                              Handle speculation_log = Handle()
 #endif
   );
 
@@ -592,6 +592,8 @@
 #ifdef GRAAL
   oop graal_installed_code() { return _graal_installed_code ; }
   void set_graal_installed_code(oop installed_code) { _graal_installed_code = installed_code;  }
+  oop speculation_log() { return _speculation_log ; }
+  void set_speculation_log(oop speculation_log) { _speculation_log = speculation_log;  }
 #endif
 
   // GC support
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Thu Dec 12 15:13:02 2013 +0100
@@ -360,7 +360,7 @@
 }
 
 // constructor used to create a method
-GraalEnv::CodeInstallResult CodeInstaller::install(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations) {
+GraalEnv::CodeInstallResult CodeInstaller::install(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log) {
   BufferBlob* buffer_blob = GraalCompiler::initialize_buffer_blob();
   if (buffer_blob == NULL) {
     return GraalEnv::cache_full;
@@ -403,7 +403,7 @@
     jint entry_bci = HotSpotCompiledNmethod::entryBCI(compiled_code);
     jint id = HotSpotCompiledNmethod::id(compiled_code);
     result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
-        GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, id, false, leaf_graph_ids, installed_code, triggered_deoptimizations);
+        GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, id, false, leaf_graph_ids, installed_code, speculation_log);
     cb = nm;
   }
 
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -86,7 +86,7 @@
 public:
 
   CodeInstaller() {};
-  GraalEnv::CodeInstallResult install(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations);
+  GraalEnv::CodeInstallResult install(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle speculation_log);
 
   static address runtime_call_target_address(oop runtime_call);
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Thu Dec 12 15:13:02 2013 +0100
@@ -561,16 +561,16 @@
 
 C2V_END
 
-C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compiled_code, jobject installed_code, jobject triggered_deoptimizations))
+C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compiled_code, jobject installed_code, jobject speculation_log))
   ResourceMark rm;
   HandleMark hm;
   Handle compiled_code_handle = JNIHandles::resolve(compiled_code);
   CodeBlob* cb = NULL;
   Handle installed_code_handle = JNIHandles::resolve(installed_code);
-  Handle triggered_deoptimizations_handle = JNIHandles::resolve(triggered_deoptimizations);
+  Handle speculation_log_handle = JNIHandles::resolve(speculation_log);
 
   CodeInstaller installer;
-  GraalEnv::CodeInstallResult result = installer.install(compiled_code_handle, cb, installed_code_handle, triggered_deoptimizations_handle);
+  GraalEnv::CodeInstallResult result = installer.install(compiled_code_handle, cb, installed_code_handle, speculation_log_handle);
 
   if (PrintCodeCacheOnCompilation) {
     stringStream s;
@@ -830,6 +830,7 @@
 #define TYPE                  "Lcom/oracle/graal/api/meta/JavaType;"
 #define METHOD                "Lcom/oracle/graal/api/meta/JavaMethod;"
 #define FIELD                 "Lcom/oracle/graal/api/meta/JavaField;"
+#define SPECULATION_LOG       "Lcom/oracle/graal/api/code/SpeculationLog;"
 #define STRING                "Ljava/lang/String;"
 #define OBJECT                "Ljava/lang/Object;"
 #define CLASS                 "Ljava/lang/Class;"
@@ -869,7 +870,7 @@
   {CC"getMaxCallTargetOffset",        CC"(J)J",                                                         FN_PTR(getMaxCallTargetOffset)},
   {CC"getMetaspaceMethod",            CC"("CLASS"I)"METASPACE_METHOD,                                   FN_PTR(getMetaspaceMethod)},
   {CC"initializeConfiguration",       CC"("HS_CONFIG")V",                                               FN_PTR(initializeConfiguration)},
-  {CC"installCode0",                  CC"("HS_COMPILED_CODE HS_INSTALLED_CODE"[Z)I",                    FN_PTR(installCode0)},
+  {CC"installCode0",                  CC"("HS_COMPILED_CODE HS_INSTALLED_CODE SPECULATION_LOG")I",      FN_PTR(installCode0)},
   {CC"notifyCompilationStatistics",   CC"(I"HS_RESOLVED_METHOD"ZIJJ"HS_INSTALLED_CODE")V",              FN_PTR(notifyCompilationStatistics)},
   {CC"printCompilationStatistics",    CC"(ZZ)V",                                                        FN_PTR(printCompilationStatistics)},
   {CC"resetCompilationStatistics",    CC"()V",                                                          FN_PTR(resetCompilationStatistics)},
--- a/src/share/vm/graal/graalEnv.cpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/graal/graalEnv.cpp	Thu Dec 12 15:13:02 2013 +0100
@@ -452,7 +452,7 @@
                                 bool has_unsafe_access,
                                 GrowableArray<jlong>* leaf_graph_ids,
                                 Handle installed_code,
-                                Handle triggered_deoptimizations) {
+                                Handle speculation_log) {
   GRAAL_EXCEPTION_CONTEXT;
   NMethodSweeper::possibly_sweep();
   nm = NULL;
@@ -497,7 +497,7 @@
                                debug_info, dependencies, code_buffer,
                                frame_words, oop_map_set,
                                handler_table, &implicit_tbl,
-                               compiler, comp_level, leaf_graph_ids, installed_code, triggered_deoptimizations);
+                               compiler, comp_level, leaf_graph_ids, installed_code, speculation_log);
 
     // Free codeBlobs
     //code_buffer->free_blob();
--- a/src/share/vm/graal/graalEnv.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/graal/graalEnv.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -146,7 +146,7 @@
                        bool                      has_unsafe_access,
                        GrowableArray<jlong>*     leaf_graph_ids,
                        Handle                    installed_code,
-                       Handle                    triggered_deoptimizations);
+                       Handle                    speculation_log);
 
   // converts the Klass* representing the holder of a method into a
   // InstanceKlass*.  This is needed since the holder of a method in
--- a/src/share/vm/graal/graalJavaAccess.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -235,6 +235,9 @@
     oop_field(HotSpotMonitorValue, slot, "Lcom/oracle/graal/api/code/StackSlot;")                                                                              \
     boolean_field(HotSpotMonitorValue, eliminated)                                                                                                             \
   end_class                                                                                                                                                    \
+  start_class(SpeculationLog)                                                                                                                                  \
+    oop_field(SpeculationLog, lastFailed, "Ljava/lang/Object;")                                                                                                \
+  end_class
   /* end*/
 
 #define START_CLASS(name)                                                                                                                                      \
--- a/src/share/vm/graal/vmStructs_graal.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/graal/vmStructs_graal.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -30,6 +30,7 @@
 
 #define VM_STRUCTS_GRAAL(nonstatic_field, static_field)                       \
   nonstatic_field(ThreadShadow, _pending_deoptimization, int)                 \
+  nonstatic_field(ThreadShadow, _pending_failed_speculation, oop)             \
 
 #define VM_TYPES_GRAAL(declare_type, declare_toplevel_type)                   \
 
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/runtime/deoptimization.cpp	Thu Dec 12 15:13:02 2013 +0100
@@ -1347,7 +1347,7 @@
     DeoptReason reason = trap_request_reason(trap_request);
     DeoptAction action = trap_request_action(trap_request);
 #ifdef GRAAL
-    short speculation_id = trap_request_speculation_id(trap_request);
+    short debug_id = trap_request_debug_id(trap_request);
 #endif
     jint unloaded_class_index = trap_request_index(trap_request); // CP idx or -1
 
@@ -1361,7 +1361,7 @@
     if (TraceDeoptimization) {
       tty->print_cr("  bci=%d pc=%d, relative_pc=%d, method=%s" GRAAL_ONLY(", speculation=%d"), trap_scope->bci(), fr.pc(), fr.pc() - nm->code_begin(), trap_scope->method()->name()->as_C_string()
 #ifdef GRAAL
-          , speculation_id
+          , debug_id
 #endif
           );
     }
@@ -1369,6 +1369,15 @@
     methodHandle    trap_method = trap_scope->method();
     int             trap_bci    = trap_scope->bci();
 #ifdef GRAAL
+    oop speculation = thread->pending_failed_speculation();
+    if (speculation != NULL) {
+      oop speculation_log = nm->speculation_log();
+      if (speculation_log != NULL) {
+        SpeculationLog::set_lastFailed(speculation_log, speculation);
+      }
+      thread->set_pending_failed_speculation(NULL);
+    }
+
     if (trap_bci == SynchronizationEntryBCI) {
       trap_bci = 0;
       Thread::current()->set_pending_monitorenter(true);
@@ -1483,7 +1492,7 @@
                    trap_action_name(action),
                    unloaded_class_index
 #ifdef GRAAL
-                   , speculation_id
+                   , debug_id
 #endif
                    );
         if (class_name != NULL) {
@@ -2007,21 +2016,21 @@
   const char* reason = trap_reason_name(trap_request_reason(trap_request));
   const char* action = trap_action_name(trap_request_action(trap_request));
 #ifdef GRAAL
-  short speculation_id = trap_request_speculation_id(trap_request);
+  short debug_id = trap_request_debug_id(trap_request);
 #endif
   size_t len;
   if (unloaded_class_index < 0) {
     len = jio_snprintf(buf, buflen, "reason='%s' action='%s'" GRAAL_ONLY(" speculation='%d'"),
                        reason, action
 #ifdef GRAAL
-                       ,speculation_id
+                       ,debug_id
 #endif
                        );
   } else {
     len = jio_snprintf(buf, buflen, "reason='%s' action='%s' index='%d'" GRAAL_ONLY(" speculation='%d'"),
                        reason, action, unloaded_class_index
 #ifdef GRAAL
-                       ,speculation_id
+                       ,debug_id
 #endif
                        );
   }
--- a/src/share/vm/runtime/deoptimization.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/runtime/deoptimization.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -105,10 +105,10 @@
   enum {
     _action_bits = 3,
     _reason_bits = 5,
-    _speculation_id_bits = 23,
+    _debug_id_bits = 23,
     _action_shift = 0,
     _reason_shift = _action_shift+_action_bits,
-    _speculation_id_shift = _reason_shift+_reason_bits,
+    _debug_id_shift = _reason_shift+_reason_bits,
     BC_CASE_LIMIT = PRODUCT_ONLY(1) NOT_PRODUCT(4) // for _deoptimization_hist
   };
 
@@ -294,10 +294,10 @@
       // standard action for unloaded CP entry
       return _unloaded_action;
   }
-  static short trap_request_speculation_id(int trap_request) {
+  static short trap_request_debug_id(int trap_request) {
       if (trap_request < 0)
         return (DeoptAction)
-          ((~(trap_request) >> _speculation_id_shift) & right_n_bits(_speculation_id_bits));
+          ((~(trap_request) >> _debug_id_shift) & right_n_bits(_debug_id_bits));
       else
         // standard action for unloaded CP entry
         return 0;
--- a/src/share/vm/runtime/thread.cpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/runtime/thread.cpp	Thu Dec 12 15:13:02 2013 +0100
@@ -834,6 +834,7 @@
   active_handles()->oops_do(f);
   // Do oop for ThreadShadow
   f->do_oop((oop*)&_pending_exception);
+  f->do_oop((oop*)&_pending_failed_speculation);
   handle_area()->oops_do(f);
 }
 
--- a/src/share/vm/runtime/vmStructs.cpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Thu Dec 12 15:13:02 2013 +0100
@@ -2563,10 +2563,10 @@
                                                                           \
   declare_constant(Deoptimization::_action_bits)                          \
   declare_constant(Deoptimization::_reason_bits)                          \
-  declare_constant(Deoptimization::_speculation_id_bits)                  \
+  declare_constant(Deoptimization::_debug_id_bits)                        \
   declare_constant(Deoptimization::_action_shift)                         \
   declare_constant(Deoptimization::_reason_shift)                         \
-  declare_constant(Deoptimization::_speculation_id_shift)                 \
+  declare_constant(Deoptimization::_debug_id_shift)                       \
                                                                           \
   /*********************/                                                 \
   /* Matcher (C2 only) */                                                 \
--- a/src/share/vm/utilities/exceptions.hpp	Wed Jan 15 15:11:47 2014 +0100
+++ b/src/share/vm/utilities/exceptions.hpp	Thu Dec 12 15:13:02 2013 +0100
@@ -63,6 +63,7 @@
  protected:
 #ifdef GRAAL
   int _pending_deoptimization;
+  oop _pending_failed_speculation;
   bool _pending_monitorenter;
 #endif
   oop  _pending_exception;                       // Thread has gc actions.
@@ -85,6 +86,7 @@
   int  exception_line() const                    { return _exception_line; }
 #ifdef GRAAL
   int  pending_deoptimization() const            { return _pending_deoptimization; }
+  oop  pending_failed_speculation() const        { return _pending_failed_speculation; }
   bool has_pending_monitorenter() const          { return _pending_monitorenter; }
 #endif
 
@@ -93,9 +95,11 @@
 #ifdef GRAAL
   static ByteSize pending_deoptimization_offset() { return byte_offset_of(ThreadShadow, _pending_deoptimization); }
   static ByteSize pending_monitorenter_offset()  { return byte_offset_of(ThreadShadow, _pending_monitorenter); }
+  static ByteSize pending_failed_speculation_offset() { return byte_offset_of(ThreadShadow, _pending_failed_speculation); }
 
   void set_pending_monitorenter(bool b)          { _pending_monitorenter = b; }
   void set_pending_deoptimization(int reason)    { _pending_deoptimization = reason; }
+  void set_pending_failed_speculation(oop failed_speculation)    { _pending_failed_speculation = failed_speculation; }
 #endif
 
   // use THROW whenever possible!
@@ -107,7 +111,7 @@
   ThreadShadow() : _pending_exception(NULL),
                    _exception_file(NULL), _exception_line(0)
 #ifdef GRAAL
-                   , _pending_monitorenter(false), _pending_deoptimization(-1)
+                   , _pending_monitorenter(false), _pending_deoptimization(-1), _pending_failed_speculation(NULL)
 #endif
   {}
 };