changeset 8892:2c0c708a0ad6

Introduce DeoptimizingNode interface
author Gilles Duboscq <duboscq@ssw.jku.at>
date Mon, 08 Apr 2013 09:26:06 +0200
parents ca82d06ec93a
children dedbfa40d6a1 6c33b2076d7c 216dce75d5ac
files graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.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.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java
diffstat 51 files changed, 535 insertions(+), 156 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Apr 08 09:26:06 2013 +0200
@@ -212,17 +212,17 @@
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
+    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting) {
         AMD64AddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
         Variable result = newVariable(loadAddress.getKind());
-        append(new LoadOp(result, loadAddress, canTrap ? state() : null));
+        append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null));
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) {
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) {
         AMD64AddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
-        LIRFrameState state = canTrap ? state() : null;
+        LIRFrameState state = deopting != null ? state(deopting) : null;
 
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
@@ -369,11 +369,11 @@
     }
 
     @Override
-    public void emitNullCheck(ValueNode v) {
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deoping) {
         assert v.kind() == Kind.Object;
         Variable obj = newVariable(Kind.Object);
         emitMove(obj, operand(v));
-        append(new AMD64Move.NullCheckOp(obj, state()));
+        append(new AMD64Move.NullCheckOp(obj, state(deoping)));
     }
 
     @Override
@@ -509,7 +509,7 @@
                 if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
                     FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
                     if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && operand(otherDivRem) == null) {
-                        Value[] results = emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()));
+                        Value[] results = emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), (DeoptimizingNode) valueNode);
                         if (divRem instanceof IntegerDivNode) {
                             setResult(divRem, results[0]);
                             setResult(otherDivRem, results[1]);
@@ -526,19 +526,20 @@
         return false;
     }
 
-    private void emitDivRem(AMD64Arithmetic op, Value a, Value b) {
+    private void emitDivRem(AMD64Arithmetic op, Value a, Value b, LIRFrameState state) {
         AllocatableValue rax = AMD64.rax.asValue(a.getKind());
         emitMove(rax, a);
-        append(new DivRemOp(op, rax, asAllocatable(b), state()));
+        append(new DivRemOp(op, rax, asAllocatable(b), state));
     }
 
-    public Value[] emitIntegerDivRem(Value a, Value b) {
+    public Value[] emitIntegerDivRem(Value a, Value b, DeoptimizingNode deopting) {
+        LIRFrameState state = state(deopting);
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IDIVREM, a, b);
+                emitDivRem(IDIVREM, a, b, state);
                 return new Value[]{emitMove(RAX_I), emitMove(RDX_I)};
             case Long:
-                emitDivRem(LDIVREM, a, b);
+                emitDivRem(LDIVREM, a, b, state);
                 return new Value[]{emitMove(RAX_L), emitMove(RDX_L)};
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -546,13 +547,13 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b) {
+    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IDIV, a, b);
+                emitDivRem(IDIV, a, b, state(deopting));
                 return emitMove(RAX_I);
             case Long:
-                emitDivRem(LDIV, a, b);
+                emitDivRem(LDIV, a, b, state(deopting));
                 return emitMove(RAX_L);
             case Float: {
                 Variable result = newVariable(a.getKind());
@@ -570,21 +571,21 @@
     }
 
     @Override
-    public Value emitRem(Value a, Value b) {
+    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IREM, a, b);
+                emitDivRem(IREM, a, b, state(deopting));
                 return emitMove(RDX_I);
             case Long:
-                emitDivRem(LREM, a, b);
+                emitDivRem(LREM, a, b, state(deopting));
                 return emitMove(RDX_L);
             case Float: {
                 RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_FREM);
-                return emitCall(stub, stub.getCallingConvention(), false, a, b);
+                return emitCall(stub, stub.getCallingConvention(), null, a, b);
             }
             case Double: {
                 RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_DREM);
-                return emitCall(stub, stub.getCallingConvention(), false, a, b);
+                return emitCall(stub, stub.getCallingConvention(), null, a, b);
             }
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -592,13 +593,14 @@
     }
 
     @Override
-    public Variable emitUDiv(Value a, Value b) {
+    public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
+        LIRFrameState state = state(deopting);
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IUDIV, a, b);
+                emitDivRem(IUDIV, a, b, state);
                 return emitMove(RAX_I);
             case Long:
-                emitDivRem(LUDIV, a, b);
+                emitDivRem(LUDIV, a, b, state);
                 return emitMove(RAX_L);
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -606,13 +608,14 @@
     }
 
     @Override
-    public Variable emitURem(Value a, Value b) {
+    public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
+        LIRFrameState state = state(deopting);
         switch (a.getKind()) {
             case Int:
-                emitDivRem(IUREM, a, b);
+                emitDivRem(IUREM, a, b, state);
                 return emitMove(RDX_I);
             case Long:
-                emitDivRem(LUREM, a, b);
+                emitDivRem(LUREM, a, b, state);
                 return emitMove(RDX_L);
             default:
                 throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Mon Apr 08 09:26:06 2013 +0200
@@ -154,18 +154,18 @@
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
+    public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting) {
         PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
         Variable result = newVariable(loadAddress.getKind());
-        append(new LoadOp(result, loadAddress, canTrap ? state() : null));
+        append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null));
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) {
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) {
         PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
         Variable input = load(inputVal);
-        append(new StoreOp(storeAddress, input, canTrap ? state() : null));
+        append(new StoreOp(storeAddress, input, deopting != null ? state(deopting) : null));
     }
 
     @Override
@@ -278,22 +278,22 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b) {
+    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
         throw new InternalError("NYI");
     }
 
     @Override
-    public Value emitRem(Value a, Value b) {
+    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
         throw new InternalError("NYI");
     }
 
     @Override
-    public Variable emitUDiv(Value a, Value b) {
+    public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
         throw new InternalError("NYI");
     }
 
     @Override
-    public Variable emitURem(Value a, Value b) {
+    public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
         throw new InternalError("NYI");
     }
 
@@ -349,7 +349,7 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
@@ -469,7 +469,7 @@
     }
 
     @Override
-    public void emitNullCheck(ValueNode v) {
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
         throw new InternalError("NYI");
     }
 }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Apr 08 09:26:06 2013 +0200
@@ -214,13 +214,13 @@
     }
 
     @Override
-    public Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) {
+    public Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode canTrap) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, boolean canTrap) {
+    public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, DeoptimizingNode canTrap) {
         // SPARC: Auto-generated method stub
 
     }
@@ -262,25 +262,25 @@
     }
 
     @Override
-    public Value emitDiv(Value a, Value b) {
+    public Value emitDiv(Value a, Value b, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public Value emitRem(Value a, Value b) {
+    public Value emitRem(Value a, Value b, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public Value emitUDiv(Value a, Value b) {
+    public Value emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public Value emitURem(Value a, Value b) {
+    public Value emitURem(Value a, Value b, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
         return null;
     }
@@ -334,7 +334,7 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
 
     }
@@ -364,7 +364,7 @@
     }
 
     @Override
-    public void emitNullCheck(ValueNode v) {
+    public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
         // SPARC: Auto-generated method stub
 
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Apr 08 09:26:06 2013 +0200
@@ -220,11 +220,11 @@
 
         plan.runPhases(PhasePosition.LOW_LEVEL, graph);
 
-        new GuardLoweringPhase(target).apply(graph);
-
         // Add safepoints to loops
         new SafepointInsertionPhase().apply(graph);
 
+        new GuardLoweringPhase(target).apply(graph);
+
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
         Debug.dump(schedule, "final schedule");
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Mon Apr 08 09:26:06 2013 +0200
@@ -218,13 +218,11 @@
         return false;
     }
 
-    public LIRFrameState state() {
-        return state(null);
-    }
-
-    public LIRFrameState state(DeoptimizationReason reason) {
-        assert lastState != null || needOnlyOopMaps() : "must have state before instruction";
-        return stateFor(lastState, reason);
+    public LIRFrameState state(DeoptimizingNode deopt) {
+        if (!deopt.canDeoptimize()) {
+            return null;
+        }
+        return stateFor(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason());
     }
 
     public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) {
@@ -332,6 +330,12 @@
             if (instr instanceof StateSplit) {
                 stateAfter = ((StateSplit) instr).stateAfter();
             }
+            if (instr instanceof DeoptimizingNode) {
+                DeoptimizingNode deopt = (DeoptimizingNode) instr;
+                if (deopt.canDeoptimize() && deopt.getDeoptimizationState() == null) {
+                    deopt.setDeoptimizationState(lastState);
+                }
+            }
             if (instr instanceof ValueNode) {
 
                 ValueNode valueNode = (ValueNode) instr;
@@ -658,8 +662,8 @@
     }
 
     @Override
-    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args) {
-        LIRFrameState info = canTrap ? state() : null;
+    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args) {
+        LIRFrameState state = info != null ? state(info) : null;
 
         // move the arguments into the correct location
         frameMap.callsMethod(cc);
@@ -671,7 +675,7 @@
             emitMove(loc, arg);
             argLocations[i] = loc;
         }
-        emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), info);
+        emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), state);
 
         if (isLegal(cc.getReturn())) {
             return emitMove(cc.getReturn());
@@ -688,25 +692,7 @@
         Value resultOperand = cc.getReturn();
         Value[] args = visitInvokeArguments(cc, x.arguments());
 
-        LIRFrameState info = null;
-        FrameState stateAfter = x.stateAfter();
-        if (stateAfter != null) {
-            // (cwimmer) I made the code that modifies the operand stack conditional. My scenario:
-            // runtime calls to, e.g.,
-            // CreateNullPointerException have no equivalent in the bytecodes, so there is no invoke
-            // bytecode.
-            // Therefore, the result of the runtime call was never pushed to the stack, and we
-            // cannot pop it here.
-            FrameState stateBeforeReturn = stateAfter;
-            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, null);
-        } else {
-            info = state();
-        }
-
-        emitCall(call, resultOperand, args, cc.getTemporaries(), info);
+        emitCall(call, resultOperand, args, cc.getTemporaries(), state(x));
 
         if (isLegal(resultOperand)) {
             setResult(x, emitMove(resultOperand));
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Apr 08 09:26:06 2013 +0200
@@ -161,7 +161,7 @@
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
-        LIRFrameState info = state();
+        LIRFrameState info = state(i);
         append(new AMD64SafepointOp(info, runtime().config, this));
     }
 
@@ -232,8 +232,8 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
-        append(new AMD64DeoptimizeOp(action, reason, state()));
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+        append(new AMD64DeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting)));
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2013, 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.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.type.*;
+
+public class DeoptimizingStubCall extends DeoptimizingFixedWithNextNode {
+
+    public DeoptimizingStubCall(Stamp stamp) {
+        super(stamp);
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/IdentityHashCodeStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -34,7 +34,7 @@
 /**
  * Node implementing a call to HotSpot's {@code graal_identityhashcode} stub.
  */
-public class IdentityHashCodeStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class IdentityHashCodeStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     @Input private final ValueNode object;
     public static final Descriptor IDENTITY_HASHCODE = new Descriptor("identity_hashcode", false, int.class, Object.class);
@@ -47,7 +47,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(IdentityHashCodeStubCall.IDENTITY_HASHCODE);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -33,7 +33,7 @@
 /**
  * Node implementing a call to HotSpot's {@code graal_monitorenter} stub.
  */
-public class MonitorEnterStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class MonitorEnterStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     @Input private final ValueNode object;
     @Input private final ValueNode lock;
@@ -48,7 +48,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorEnterStubCall.MONITORENTER);
-        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.operand(lock));
+        gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object), gen.operand(lock));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -35,7 +35,7 @@
 /**
  * Node implementing a call to HotSpot's {@code graal_monitorexit} stub.
  */
-public class MonitorExitStubCall extends FixedWithNextNode implements LIRGenLowerable, MonitorReference {
+public class MonitorExitStubCall extends DeoptimizingStubCall implements LIRGenLowerable, MonitorReference {
 
     @Input private final ValueNode object;
     private int lockDepth;
@@ -60,7 +60,7 @@
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
         StackSlot slot = hsGen.getLockSlot(lockDepth);
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorExitStubCall.MONITOREXIT);
-        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.emitLea(slot));
+        gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object), gen.emitLea(slot));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -35,7 +35,7 @@
 /**
  * Node implementing a call to the {@code new_array} stub.
  */
-public class NewArraySlowStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewArraySlowStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -62,7 +62,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY_SLOW);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), gen.operand(length));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub), gen.operand(length));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -36,7 +36,7 @@
 /**
  * A call to the {@link NewArrayStub}.
  */
-public class NewArrayStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewArrayStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -63,7 +63,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), gen.operand(length));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub), gen.operand(length));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -35,7 +35,7 @@
 /**
  * Node implementing a call to HotSpot's {@code new_instance} stub.
  */
-public class NewInstanceSlowStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewInstanceSlowStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -60,7 +60,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_INSTANCE_SLOW);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -36,7 +36,7 @@
 /**
  * A call to the {@link NewInstanceStub}.
  */
-public class NewInstanceStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewInstanceStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -61,7 +61,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_INSTANCE);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -36,7 +36,7 @@
 /**
  * Node implementing a call to HotSpot's {@code new_multi_array} stub.
  */
-public class NewMultiArrayStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class NewMultiArrayStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     private static final Stamp defaultStamp = StampFactory.objectNonNull();
 
@@ -65,7 +65,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NewMultiArrayStubCall.NEW_MULTI_ARRAY);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), Constant.forInt(rank), gen.operand(dims));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub), Constant.forInt(rank), gen.operand(dims));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -69,7 +69,7 @@
             parameters.add(frameState.localAt(slot));
         }
         Value[] args = gen.visitInvokeArguments(cc, parameters);
-        Value entry = gen.emitLoad(Kind.Long, gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0, false);
+        Value entry = gen.emitLoad(Kind.Long, gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0, null);
         HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen;
         hsgen.emitTailcall(args, entry);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ThreadIsInterruptedStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -37,7 +37,7 @@
 /**
  * Node implementing a call to HotSpot's ThreadIsInterrupted stub.
  */
-public class ThreadIsInterruptedStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class ThreadIsInterruptedStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     @Input private final ValueNode thread;
     @Input private final ValueNode clearIsInterrupted;
@@ -52,7 +52,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(ThreadIsInterruptedStubCall.THREAD_IS_INTERRUPTED);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(thread), gen.operand(clearIsInterrupted));
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(thread), gen.operand(clearIsInterrupted));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -28,7 +28,6 @@
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
@@ -51,15 +50,7 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        String where;
-        try {
-            LIRFrameState state = gen.state();
-            BytecodePosition pos = state.topFrame;
-            where = "near or " + CodeUtil.append(new StringBuilder(100), pos).toString().replace(CodeUtil.NEW_LINE, CodeUtil.NEW_LINE + "\t");
-        } catch (Throwable t) {
-            // Report a less accurate location when debug info cannot be obtained
-            where = "in compiled code for " + MetaUtil.format("%H.%n(%p)", gen.method());
-        }
+        String where = "in compiled code for " + MetaUtil.format("%H.%n(%p)", gen.method());
 
         HotSpotRuntime runtime = (HotSpotRuntime) gen.getRuntime();
         Constant whereArg = Constant.forObject(runtime.registerGCRoot(where));
@@ -71,7 +62,7 @@
         }
 
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(VMErrorNode.VM_ERROR);
-        gen.emitCall(stub, stub.getCallingConvention(), false, whereArg, formatArg, gen.operand(value));
+        gen.emitCall(stub, stub.getCallingConvention(), null, whereArg, formatArg, gen.operand(value));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -32,7 +32,7 @@
 /**
  * Node implementing a call to HotSpot's object pointer verification stub.
  */
-public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable {
+public class VerifyOopStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
 
     @Input private final ValueNode object;
     public static final Descriptor VERIFY_OOP = new Descriptor("verify_oop", false, void.class, Object.class);
@@ -45,7 +45,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(VerifyOopStubCall.VERIFY_OOP);
-        gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object));
+        gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPostStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -48,7 +48,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(WriteBarrierPostStubCall.WBPOSTCALL);
-        gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(object), gen.operand(card));
+        gen.emitCall(stub, stub.getCallingConvention(), null, gen.operand(object), gen.operand(card));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrierPreStubCall.java	Mon Apr 08 09:26:06 2013 +0200
@@ -45,7 +45,7 @@
     @Override
     public void generate(LIRGenerator gen) {
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(WriteBarrierPreStubCall.WBPRECALL);
-        gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(object));
+        gen.emitCall(stub, stub.getCallingConvention(), null, gen.operand(object));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Mon Apr 08 09:26:06 2013 +0200
@@ -98,7 +98,7 @@
         @Override
         public void generate(LIRGenerator gen) {
             RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(descriptor);
-            gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key));
+            gen.emitCall(stub, stub.getCallingConvention(), null, gen.operand(in), gen.operand(out), gen.operand(key));
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Mon Apr 08 09:26:06 2013 +0200
@@ -119,7 +119,7 @@
         @Override
         public void generate(LIRGenerator gen) {
             RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(descriptor);
-            gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength));
+            gen.emitCall(stub, stub.getCallingConvention(), null, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength));
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -29,7 +29,9 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}")
-public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable {
+public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, LIRLowerable, DeoptimizingNode {
+
+    @Input private FrameState deoptState;
 
     private final DeoptimizationAction action;
     private final DeoptimizationReason reason;
@@ -50,9 +52,34 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.emitDeoptimize(action, reason);
+        gen.emitDeoptimize(action, this);
     }
 
     @NodeIntrinsic
     public static native void deopt(@ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter DeoptimizationReason reason);
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        deoptState = f;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return reason;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return false;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2013, 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.nodes;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.type.*;
+
+public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode {
+
+    @Input private FrameState deoptState;
+
+    public DeoptimizingFixedWithNextNode(Stamp stamp) {
+        super(stamp);
+    }
+
+    public DeoptimizingFixedWithNextNode(Stamp stamp, List<ValueNode> dependencies) {
+        super(stamp, dependencies);
+    }
+
+    public DeoptimizingFixedWithNextNode(Stamp stamp, ValueNode... dependencies) {
+        super(stamp, dependencies);
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        deoptState = f;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, 2013, 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.nodes;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Interface that needs to be implemented by nodes which need deoptimization information.
+ * 
+ */
+public interface DeoptimizingNode {
+
+    /**
+     * Returns true if this particular instance needs deoptimization information.
+     * 
+     * @return true if this particular instance needs deoptimization information
+     */
+    boolean canDeoptimize();
+
+    /**
+     * Returns the deoptimization information associated with this node if any.
+     * 
+     * @return the deoptimization information associated with this node if any.
+     */
+    FrameState getDeoptimizationState();
+
+    /**
+     * Set the deoptimization information associated with this node.
+     * 
+     * @param state the FrameState which represents the deoptimization information.
+     */
+    void setDeoptimizationState(FrameState state);
+
+    /**
+     * Returns the reason for deoptimization triggered by this node. If deoptimization at this point
+     * can happen for external reasons (i.e. not explicitely triggered by this node) this method can
+     * return null.
+     * 
+     * @return the reason for deoptimization triggered by this node.
+     */
+    DeoptimizationReason getDeoptimizationReason();
+
+    /**
+     * Returns true if this node needs deoptimization information for stack-walking purposes because
+     * it is a call-site. While most other nodes use deoptimization information representing a state
+     * that happened before them, these nodes use a state that is valid during the call itself.
+     * 
+     * @return true if this node needs deoptimization information for stack-walking purposes.
+     */
+    boolean isCallSiteDeoptimization();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/Invoke.java	Mon Apr 08 09:26:06 2013 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 
-public interface Invoke extends StateSplit, Lowerable {
+public interface Invoke extends StateSplit, Lowerable, DeoptimizingNode {
 
     FixedNode next();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -175,4 +175,29 @@
             stateAfter.safeDelete();
         }
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return stateDuring();
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -221,4 +221,29 @@
     public double probability(BeginNode successor) {
         return successor == next ? 1 - EXCEPTION_PROBA : EXCEPTION_PROBA;
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return stateDuring();
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        throw new IllegalStateException();
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -29,7 +30,7 @@
 /**
  * Marks a position in the graph where a safepoint should be emitted.
  */
-public class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
+public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, Node.IterableNodeType {
 
     public SafepointNode() {
         this(StampFactory.forVoid());
@@ -43,4 +44,14 @@
     public void generate(LIRGeneratorTool gen) {
         gen.visitSafepointNode(this);
     }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -23,12 +23,10 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
-@NodeInfo(shortName = "/")
-public class FixedBinaryNode extends FixedWithNextNode {
+public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
@@ -46,4 +44,9 @@
         this.x = x;
         this.y = y;
     }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.ArithmeticException;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -53,6 +53,6 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()), null));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -49,6 +49,6 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()), null));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -109,6 +109,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitDiv(gen.operand(x()), gen.operand(y()), this));
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return y().integerStamp().contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -66,6 +66,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitRem(gen.operand(x()), gen.operand(y()), this));
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return y().integerStamp().contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -67,6 +67,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitUDiv(gen.operand(x()), gen.operand(y()), this));
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return y().integerStamp().contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -66,6 +66,11 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitURem(gen.operand(x()), gen.operand(y())));
+        gen.setResult(this, gen.emitURem(gen.operand(x()), gen.operand(y()), this));
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return y().integerStamp().contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/Access.java	Mon Apr 08 09:26:06 2013 +0200
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
-public interface Access {
+public interface Access extends DeoptimizingNode {
 
     ValueNode object();
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,7 +34,7 @@
  * {@linkplain #nullCheckLocation() location}. The access does not include a null check on the
  * object.
  */
-public abstract class AccessNode extends FixedWithNextNode implements Access {
+public abstract class AccessNode extends DeoptimizingFixedWithNextNode implements Access {
 
     @Input private ValueNode object;
     @Input private ValueNode location;
@@ -81,4 +82,14 @@
     public Node node() {
         return this;
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return nullCheck;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.NullCheckException;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -33,6 +34,7 @@
 
     @Input private ValueNode object;
     @Input private LocationNode location;
+    @Input private FrameState deoptState;
     private boolean nullCheck;
 
     public ValueNode object() {
@@ -78,5 +80,30 @@
         return this;
     }
 
+    @Override
+    public boolean canDeoptimize() {
+        return nullCheck;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.NullCheckException;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        deoptState = f;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return false;
+    }
+
     public abstract Access asFixedNode();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -53,7 +53,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, location().generateLoad(gen, object(), getNullCheck()));
+        gen.setResult(this, location().generateLoad(gen, object(), this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -86,12 +86,12 @@
     }
 
     @Override
-    public Value generateLoad(LIRGeneratorTool gen, ValueNode base, boolean canTrap) {
-        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), canTrap);
+    public Value generateLoad(LIRGeneratorTool gen, ValueNode base, DeoptimizingNode deopting) {
+        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), deopting);
     }
 
     @Override
-    public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, boolean canTrap) {
-        gen.emitStore(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), gen.operand(value), canTrap);
+    public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, DeoptimizingNode deopting) {
+        gen.emitStore(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), gen.operand(value), deopting);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -107,11 +107,11 @@
         return gen.emitLea(gen.operand(base), displacement(), Value.ILLEGAL, 0);
     }
 
-    public Value generateLoad(LIRGeneratorTool gen, ValueNode base, boolean canTrap) {
-        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, canTrap);
+    public Value generateLoad(LIRGeneratorTool gen, ValueNode base, DeoptimizingNode deopting) {
+        return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, deopting);
     }
 
-    public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, boolean canTrap) {
-        gen.emitStore(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, gen.operand(value), canTrap);
+    public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, DeoptimizingNode deopting) {
+        gen.emitStore(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, gen.operand(value), deopting);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public class NullCheckNode extends FixedWithNextNode implements LIRLowerable {
+public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
 
     @Input public ValueNode object;
 
@@ -41,6 +42,16 @@
 
     @Override
     public void generate(LIRGeneratorTool generator) {
-        generator.emitNullCheck(object);
+        generator.emitNullCheck(object, this);
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return DeoptimizationReason.NullCheckException;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -57,7 +57,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, location().generateLoad(gen, object(), getNullCheck()));
+        gen.setResult(this, location().generateLoad(gen, object(), this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -30,9 +30,10 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "RuntimeCall#{p#descriptor/s}")
-public final class RuntimeCallNode extends AbstractCallNode implements LIRLowerable {
+public final class RuntimeCallNode extends AbstractCallNode implements LIRLowerable, DeoptimizingNode {
 
     private final Descriptor descriptor;
+    @Input private FrameState deoptState;
 
     public RuntimeCallNode(Descriptor descriptor, ValueNode... arguments) {
         super(StampFactory.forKind(Kind.fromJavaClass(descriptor.getResultType())), arguments);
@@ -65,4 +66,41 @@
         }
         return super.toString(verbosity);
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        if (deoptState != null) {
+            return deoptState;
+        } else if (stateAfter() != null) {
+            FrameState stateDuring = stateAfter();
+            if ((stateDuring.stackSize() > 0 && stateDuring.stackAt(stateDuring.stackSize() - 1) == this) || (stateDuring.stackSize() > 1 && stateDuring.stackAt(stateDuring.stackSize() - 2) == this)) {
+                stateDuring = stateDuring.duplicateModified(stateDuring.bci, stateDuring.rethrowException(), this.kind());
+            }
+            return stateDuring;
+        }
+        return null;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        if (deoptState != null) {
+            throw new IllegalStateException();
+        }
+        deoptState = f;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return stateAfter() != null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -59,7 +59,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        location().generateStore(gen, object(), value(), getNullCheck());
+        location().generateStore(gen, object(), value(), this);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -32,10 +33,11 @@
  * This node is used to perform the finalizer registration at the end of the java.lang.Object
  * constructor.
  */
-public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable, Virtualizable {
+public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode {
 
     public static final Descriptor REGISTER_FINALIZER = new Descriptor("registerFinalizer", true, void.class, Object.class);
 
+    @Input private FrameState deoptState;
     @Input private ValueNode object;
 
     public ValueNode object() {
@@ -50,7 +52,7 @@
     @Override
     public void generate(LIRGeneratorTool gen) {
         RuntimeCallTarget call = gen.getRuntime().lookupRuntimeCall(REGISTER_FINALIZER);
-        gen.emitCall(call, call.getCallingConvention(), true, gen.operand(object()));
+        gen.emitCall(call, call.getCallingConvention(), this, gen.operand(object()));
     }
 
     @Override
@@ -83,6 +85,31 @@
         }
     }
 
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+
+    @Override
+    public FrameState getDeoptimizationState() {
+        return deoptState;
+    }
+
+    @Override
+    public void setDeoptimizationState(FrameState f) {
+        deoptState = f;
+    }
+
+    @Override
+    public DeoptimizationReason getDeoptimizationReason() {
+        return null;
+    }
+
+    @Override
+    public boolean isCallSiteDeoptimization() {
+        return false;
+    }
+
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void register(Object thisObj) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Mon Apr 08 09:26:06 2013 +0200
@@ -57,9 +57,9 @@
 
     public abstract void emitMove(Value dst, Value src);
 
-    public abstract Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap);
+    public abstract Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting);
 
-    public abstract void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, boolean canTrap);
+    public abstract void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, DeoptimizingNode deopting);
 
     public abstract Value emitLea(Value base, int displacement, Value index, int scale);
 
@@ -73,13 +73,13 @@
 
     public abstract Value emitMul(Value a, Value b);
 
-    public abstract Value emitDiv(Value a, Value b);
+    public abstract Value emitDiv(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitRem(Value a, Value b);
+    public abstract Value emitRem(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitUDiv(Value a, Value b);
+    public abstract Value emitUDiv(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitURem(Value a, Value b);
+    public abstract Value emitURem(Value a, Value b, DeoptimizingNode deopting);
 
     public abstract Value emitAnd(Value a, Value b);
 
@@ -97,11 +97,11 @@
 
     public abstract void emitMembar(int barriers);
 
-    public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason);
+    public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting);
 
-    public abstract void emitNullCheck(ValueNode v);
+    public abstract void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
 
-    public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args);
+    public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args);
 
     public abstract void emitIf(IfNode i);
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -47,7 +47,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), 0, Value.ILLEGAL, 0, false));
+        gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), 0, Value.ILLEGAL, 0, null));
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Wed Mar 27 15:31:23 2013 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Mon Apr 08 09:26:06 2013 +0200
@@ -50,7 +50,7 @@
     @Override
     public void generate(LIRGeneratorTool gen) {
         Value v = gen.operand(value);
-        gen.emitStore(kind, gen.operand(address), 0, Value.ILLEGAL, 0, v, false);
+        gen.emitStore(kind, gen.operand(address), 0, Value.ILLEGAL, 0, v, null);
     }
 
     /*