changeset 15456:bb97b75d1d65

AMD64: implemented DeoptimizationStub.deoptimizationHandler
author twisti
date Wed, 30 Apr 2014 15:41:44 -1000
parents 6e036e2a2091
children c0e1a8693e0e
files graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizationStub.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64UncommonTrapStub.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.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/HotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/runtime/deoptimization.cpp
diffstat 35 files changed, 710 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java	Wed Apr 30 15:41:44 2014 -1000
@@ -79,6 +79,14 @@
         }
     }
 
+    public final void movptr(Register dst, AMD64Address src) {
+        movq(dst, src);
+    }
+
+    public final void movptr(AMD64Address dst, Register src) {
+        movq(dst, src);
+    }
+
     public final void movptr(AMD64Address dst, int src) {
         movslq(dst, src);
     }
@@ -277,7 +285,7 @@
     /**
      * Emit code to save a given set of callee save registers in the {@linkplain CalleeSaveLayout
      * CSA} within the frame.
-     * 
+     *
      * @param csl the description of the CSA
      * @param frameToCSA offset from the frame pointer to the CSA
      */
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java	Wed Apr 30 15:41:44 2014 -1000
@@ -27,7 +27,6 @@
 import java.util.*;
 import java.util.Map.Entry;
 
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchStatement.java	Wed Apr 30 15:41:44 2014 -1000
@@ -28,7 +28,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.match.MatchPattern.MatchResultCode;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizationStub.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizationStub.java	Wed Apr 30 15:41:44 2014 -1000
@@ -35,7 +35,7 @@
 
     public AMD64DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
         super(providers, target, linkage);
-        registerConfig = new AMD64HotSpotRegisterConfig(target.arch, HotSpotGraalRuntime.runtime().getConfig(), new Register[]{rax, rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14});
+        registerConfig = new AMD64HotSpotRegisterConfig(target.arch, HotSpotGraalRuntime.runtime().getConfig(), new Register[]{rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14});
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Wed Apr 30 15:41:44 2014 -1000
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotHostBackend.*;
 
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Apr 30 15:41:44 2014 -1000
@@ -312,7 +312,7 @@
             MarkId.recordMark(crb, MarkId.EXCEPTION_HANDLER_ENTRY);
             AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null);
             MarkId.recordMark(crb, MarkId.DEOPT_HANDLER_ENTRY);
-            AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_HANDLER), null, false, null);
+            AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER), null, false, null);
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Wed Apr 30 15:41:44 2014 -1000
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotHostBackend.*;
 
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java	Wed Apr 30 15:41:44 2014 -1000
@@ -31,6 +31,7 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -41,7 +42,7 @@
 @Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME")
 final class AMD64HotSpotEnterUnpackFramesStackFrameOp extends AMD64LIRInstruction {
 
-    private final Register thread;
+    private final Register threadRegister;
     private final int threadLastJavaSpOffset;
     private final int threadLastJavaPcOffset;
     private final int threadLastJavaFpOffset;
@@ -49,32 +50,51 @@
     @Alive(REG) AllocatableValue senderSp;
     @Alive(REG) AllocatableValue senderFp;
 
-    AMD64HotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc, AllocatableValue senderSp,
-                    AllocatableValue senderFp) {
-        this.thread = thread;
+    private final SaveRegistersOp saveRegisterOp;
+
+    AMD64HotSpotEnterUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc,
+                    AllocatableValue senderSp, AllocatableValue senderFp, SaveRegistersOp saveRegisterOp) {
+        this.threadRegister = threadRegister;
         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
         this.threadLastJavaPcOffset = threadLastJavaPcOffset;
         this.threadLastJavaFpOffset = threadLastJavaFpOffset;
         this.framePc = framePc;
         this.senderSp = senderSp;
         this.senderFp = senderFp;
+        this.saveRegisterOp = saveRegisterOp;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-        final int totalFrameSize = crb.frameMap.totalFrameSize();
+        FrameMap frameMap = crb.frameMap;
+        RegisterConfig registerConfig = frameMap.registerConfig;
+        RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap);
+        Register stackPointerRegister = registerConfig.getFrameRegister();
+        final int totalFrameSize = frameMap.totalFrameSize();
+
+        // Push return address.
         masm.push(asRegister(framePc));
+
+        // Push base pointer.
         masm.push(asRegister(senderFp));
-        masm.movq(rbp, rsp);
+        masm.movq(rbp, stackPointerRegister);
 
         /*
          * Allocate a full sized frame. Since return address and base pointer are already in place
          * (see above) we allocate two words less.
          */
-        masm.decrementq(rsp, totalFrameSize - 2 * crb.target.wordSize);
+        masm.decrementq(stackPointerRegister, totalFrameSize - 2 * crb.target.wordSize);
+
+        // Save return registers after moving the frame.
+        final int stackSlotSize = frameMap.stackSlotSize();
+        Register integerResultRegister = registerConfig.getReturnRegister(Kind.Long);
+        masm.movptr(new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize), integerResultRegister);
+
+        Register floatResultRegister = registerConfig.getReturnRegister(Kind.Double);
+        masm.movdbl(new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize), floatResultRegister);
 
         // Set up last Java values.
-        masm.movq(new AMD64Address(thread, threadLastJavaSpOffset), rsp);
+        masm.movq(new AMD64Address(threadRegister, threadLastJavaSpOffset), stackPointerRegister);
 
         /*
          * Save the PC since it cannot easily be retrieved using the last Java SP after we aligned
@@ -82,12 +102,12 @@
          * blob.
          */
         masm.leaq(rax, new AMD64Address(rip, 0));
-        masm.movq(new AMD64Address(thread, threadLastJavaPcOffset), rax);
+        masm.movq(new AMD64Address(threadRegister, threadLastJavaPcOffset), rax);
 
         // Use BP because the frames look interpreted now.
-        masm.movq(new AMD64Address(thread, threadLastJavaFpOffset), rbp);
+        masm.movq(new AMD64Address(threadRegister, threadLastJavaFpOffset), rbp);
 
         // Align the stack for the following unpackFrames call.
-        masm.andq(rsp, -(crb.target.stackAlignment));
+        masm.andq(stackPointerRegister, -(crb.target.stackAlignment));
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Wed Apr 30 15:41:44 2014 -1000
@@ -26,10 +26,10 @@
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.api.meta.Value.*;
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
+import static com.oracle.graal.hotspot.HotSpotHostBackend.*;
 import static com.oracle.graal.hotspot.replacements.AESCryptSubstitutions.*;
 import static com.oracle.graal.hotspot.replacements.CRC32Substitutions.*;
 import static com.oracle.graal.hotspot.replacements.CipherBlockChainingSubstitutions.*;
@@ -63,7 +63,8 @@
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, null, exceptionCc, NOT_REEXECUTABLE, ANY_LOCATION));
         register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, ANY_LOCATION));
 
-        link(new AMD64DeoptimizationStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
+        link(new AMD64DeoptimizationStub(providers, target, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
+        link(new AMD64UncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS)));
 
         // When the java.ext.dirs property is modified then the crypto classes might not be found.
         // If that's the case we ignore the ClassNotFoundException and continue since we cannot
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Apr 30 15:41:44 2014 -1000
@@ -41,6 +41,7 @@
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.data.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
@@ -189,8 +190,8 @@
         super.emitForeignCall(linkage, result, arguments, temps, info);
     }
 
-    public void emitLeaveCurrentStackFrame() {
-        append(new AMD64HotSpotLeaveCurrentStackFrameOp());
+    public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) {
+        append(new AMD64HotSpotLeaveCurrentStackFrameOp(saveRegisterOp));
     }
 
     public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
@@ -199,18 +200,18 @@
         append(new AMD64HotSpotLeaveDeoptimizedStackFrameOp(frameSizeVariable, initialInfoVariable));
     }
 
-    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
-        Register thread = getProviders().getRegisters().getThreadRegister();
+    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) {
+        Register threadRegister = getProviders().getRegisters().getThreadRegister();
         Variable framePcVariable = load(framePc);
         Variable senderSpVariable = load(senderSp);
         Variable senderFpVariable = load(senderFp);
-        append(new AMD64HotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), framePcVariable,
-                        senderSpVariable, senderFpVariable));
+        append(new AMD64HotSpotEnterUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), framePcVariable,
+                        senderSpVariable, senderFpVariable, saveRegisterOp));
     }
 
-    public void emitLeaveUnpackFramesStackFrame() {
-        Register thread = getProviders().getRegisters().getThreadRegister();
-        append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset()));
+    public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) {
+        Register threadRegister = getProviders().getRegisters().getThreadRegister();
+        append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), saveRegisterOp));
     }
 
     /**
@@ -321,6 +322,21 @@
         return result;
     }
 
+    public Value emitDeoptimizationFetchUnrollInfoCall(SaveRegistersOp saveRegisterOp) {
+        ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(DeoptimizationFetchUnrollInfoCallNode.FETCH_UNROLL_INFO);
+
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread));
+        Variable result = super.emitForeignCall(linkage, null, thread.asValue(Kind.Long));
+        append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread));
+
+        Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = ((AMD64HotSpotLIRGenerationResult) getResult()).getCalleeSaveInfo();
+        assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo);
+        calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp);
+
+        return result;
+    }
+
     protected AMD64ZapRegistersOp emitZapRegisters(Register[] zappedRegisters, Constant[] zapValues) {
         AMD64ZapRegistersOp zap = new AMD64ZapRegistersOp(zappedRegisters, zapValues);
         append(zap);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java	Wed Apr 30 15:41:44 2014 -1000
@@ -24,19 +24,50 @@
 
 import static com.oracle.graal.amd64.AMD64.*;
 
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.asm.*;
 
 /**
- * Pops the current frame off the stack including the return address.
+ * Pops the current frame off the stack including the return address and restores the return
+ * registers stored on the stack.
  */
 @Opcode("LEAVE_CURRENT_STACK_FRAME")
 final class AMD64HotSpotLeaveCurrentStackFrameOp extends AMD64HotSpotEpilogueOp {
 
+    private final SaveRegistersOp saveRegisterOp;
+
+    public AMD64HotSpotLeaveCurrentStackFrameOp(SaveRegistersOp saveRegisterOp) {
+        this.saveRegisterOp = saveRegisterOp;
+    }
+
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        FrameMap frameMap = crb.frameMap;
+        RegisterConfig registerConfig = frameMap.registerConfig;
+        RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap);
+        Register stackPointer = registerConfig.getFrameRegister();
+
+        // Restore integer result register.
+        final int stackSlotSize = frameMap.stackSlotSize();
+        Register integerResultRegister = registerConfig.getReturnRegister(Kind.Long);
+        masm.movptr(integerResultRegister, new AMD64Address(stackPointer, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize));
+        masm.movptr(rdx, new AMD64Address(stackPointer, registerSaveLayout.registerToSlot(rdx) * stackSlotSize));
+
+        // Restore float result register.
+        Register floatResultRegister = registerConfig.getReturnRegister(Kind.Double);
+        masm.movdbl(floatResultRegister, new AMD64Address(stackPointer, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize));
+
+        /*
+         * All of the register save area will be popped of the stack. Only the return address
+         * remains.
+         */
         leaveFrameAndRestoreRbp(crb, masm);
-        masm.addq(rsp, crb.target.arch.getReturnAddressSize());
+
+        // Remove return address.
+        masm.addq(stackPointer, crb.target.arch.getReturnAddressSize());
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveDeoptimizedStackFrameOp.java	Wed Apr 30 15:41:44 2014 -1000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -26,13 +26,14 @@
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
- * Pops the current frame off the stack including the return address.
+ * Pops a deoptimized stack frame off the stack including the return address.
  */
 @Opcode("LEAVE_DEOPTIMIZED_STACK_FRAME")
 final class AMD64HotSpotLeaveDeoptimizedStackFrameOp extends AMD64HotSpotEpilogueOp {
@@ -47,9 +48,13 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-        masm.addq(rsp, asRegister(frameSize));
-        // Restore the frame pointer before stack bang because if a stack overflow is thrown it
-        // needs to be pushed (and preserved).
+        Register stackPointer = crb.frameMap.registerConfig.getFrameRegister();
+        masm.addq(stackPointer, asRegister(frameSize));
+
+        /*
+         * Restore the frame pointer before stack bang because if a stack overflow is thrown it
+         * needs to be pushed (and preserved).
+         */
         masm.movq(rbp, asRegister(framePointer));
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java	Wed Apr 30 15:41:44 2014 -1000
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
-import static com.oracle.graal.amd64.AMD64.*;
-
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -38,26 +38,42 @@
 @Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME")
 final class AMD64HotSpotLeaveUnpackFramesStackFrameOp extends AMD64LIRInstruction {
 
-    private final Register thread;
+    private final Register threadRegister;
     private final int threadLastJavaSpOffset;
     private final int threadLastJavaPcOffset;
     private final int threadLastJavaFpOffset;
 
-    AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset) {
-        this.thread = thread;
+    private final SaveRegistersOp saveRegisterOp;
+
+    AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, SaveRegistersOp saveRegisterOp) {
+        this.threadRegister = threadRegister;
         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
         this.threadLastJavaPcOffset = threadLastJavaPcOffset;
         this.threadLastJavaFpOffset = threadLastJavaFpOffset;
+        this.saveRegisterOp = saveRegisterOp;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        FrameMap frameMap = crb.frameMap;
+        RegisterConfig registerConfig = frameMap.registerConfig;
+        RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap);
+        Register stackPointerRegister = registerConfig.getFrameRegister();
+
         // Restore stack pointer.
-        masm.movq(rsp, new AMD64Address(thread, threadLastJavaSpOffset));
+        masm.movq(stackPointerRegister, new AMD64Address(threadRegister, threadLastJavaSpOffset));
 
         // Clear last Java frame values.
-        masm.movslq(new AMD64Address(thread, threadLastJavaSpOffset), 0);
-        masm.movslq(new AMD64Address(thread, threadLastJavaPcOffset), 0);
-        masm.movslq(new AMD64Address(thread, threadLastJavaFpOffset), 0);
+        masm.movslq(new AMD64Address(threadRegister, threadLastJavaSpOffset), 0);
+        masm.movslq(new AMD64Address(threadRegister, threadLastJavaPcOffset), 0);
+        masm.movslq(new AMD64Address(threadRegister, threadLastJavaFpOffset), 0);
+
+        // Restore return values.
+        final int stackSlotSize = frameMap.stackSlotSize();
+        Register integerResultRegister = registerConfig.getReturnRegister(Kind.Long);
+        masm.movptr(integerResultRegister, new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize));
+
+        Register floatResultRegister = registerConfig.getReturnRegister(Kind.Double);
+        masm.movdbl(floatResultRegister, new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize));
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64UncommonTrapStub.java	Wed Apr 30 15:41:44 2014 -1000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 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.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.*;
+
+final class AMD64UncommonTrapStub extends UncommonTrapStub {
+
+    private RegisterConfig registerConfig;
+
+    public AMD64UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
+        super(providers, target, linkage);
+        Register[] allocatable = new Register[]{rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14};
+        registerConfig = new AMD64HotSpotRegisterConfig(target.arch, HotSpotGraalRuntime.runtime().getConfig(), allocatable);
+    }
+
+    @Override
+    public RegisterConfig getRegisterConfig() {
+        return registerConfig;
+    }
+}
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Wed Apr 30 15:41:44 2014 -1000
@@ -281,31 +281,8 @@
         return result;
     }
 
-    public void emitLeaveCurrentStackFrame() {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public void emitLeaveUnpackFramesStackFrame() {
-        throw GraalInternalError.unimplemented();
-    }
-
     public SaveRegistersOp emitSaveAllRegisters() {
         throw GraalInternalError.unimplemented();
     }
 
-    public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
-        throw GraalInternalError.unimplemented();
-    }
 }
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLIRGenerator.java	Wed Apr 30 15:41:44 2014 -1000
@@ -72,31 +72,8 @@
         throw GraalInternalError.unimplemented();
     }
 
-    public void emitLeaveCurrentStackFrame() {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public void emitLeaveUnpackFramesStackFrame() {
-        throw GraalInternalError.unimplemented();
-    }
-
     public SaveRegistersOp emitSaveAllRegisters() {
         throw GraalInternalError.unimplemented();
     }
 
-    public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
-        throw GraalInternalError.unimplemented();
-    }
-
-    public Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
-        throw GraalInternalError.unimplemented();
-    }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Wed Apr 30 15:41:44 2014 -1000
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotHostBackend.*;
 
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.lir.*;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Apr 30 15:41:44 2014 -1000
@@ -232,7 +232,7 @@
             MarkId.recordMark(crb, MarkId.EXCEPTION_HANDLER_ENTRY);
             SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null);
             MarkId.recordMark(crb, MarkId.DEOPT_HANDLER_ENTRY);
-            SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(DEOPT_HANDLER), null, false, null);
+            SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER), null, false, null);
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Wed Apr 30 15:41:44 2014 -1000
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotHostBackend.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Wed Apr 30 15:41:44 2014 -1000
@@ -24,10 +24,10 @@
 
 import static com.oracle.graal.api.meta.LocationIdentity.*;
 import static com.oracle.graal.api.meta.Value.*;
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
+import static com.oracle.graal.hotspot.HotSpotHostBackend.*;
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Apr 30 15:41:44 2014 -1000
@@ -300,7 +300,7 @@
         return emitSaveRegisters(savedRegisters, savedRegisterLocations, false);
     }
 
-    public void emitLeaveCurrentStackFrame() {
+    public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) {
         append(new SPARCHotSpotLeaveCurrentStackFrameOp());
     }
 
@@ -308,7 +308,7 @@
         append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp());
     }
 
-    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp) {
+    public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) {
         Register thread = getProviders().getRegisters().getThreadRegister();
         Variable framePcVariable = load(framePc);
         Variable senderSpVariable = load(senderSp);
@@ -316,7 +316,7 @@
         append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable));
     }
 
-    public void emitLeaveUnpackFramesStackFrame() {
+    public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) {
         Register thread = getProviders().getRegisters().getThreadRegister();
         append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset()));
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Wed Apr 30 15:41:44 2014 -1000
@@ -45,11 +45,6 @@
 public abstract class HotSpotBackend extends Backend {
 
     /**
-     * Descriptor for {@link DeoptimizationStub}.
-     */
-    public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class);
-
-    /**
      * Descriptor for {@link ExceptionHandlerStub}. This stub is called by the
      * {@linkplain HotSpotVMConfig#codeInstallerMarkIdExceptionHandlerEntry exception handler} in a
      * compiled method.
@@ -57,11 +52,6 @@
     public static final ForeignCallDescriptor EXCEPTION_HANDLER = new ForeignCallDescriptor("exceptionHandler", void.class, Object.class, Word.class);
 
     /**
-     * Descriptor for SharedRuntime::deopt_blob()-&gt;unpack().
-     */
-    public static final ForeignCallDescriptor DEOPT_HANDLER = new ForeignCallDescriptor("deoptHandler", void.class);
-
-    /**
      * Descriptor for SharedRuntime::get_ic_miss_stub().
      */
     public static final ForeignCallDescriptor IC_MISS_HANDLER = new ForeignCallDescriptor("icMissHandler", void.class);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java	Wed Apr 30 15:41:44 2014 -1000
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.hotspot;
 
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotHostBackend.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CompilationResult.Call;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Wed Apr 30 15:41:44 2014 -1000
@@ -31,6 +31,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -39,6 +40,16 @@
 public abstract class HotSpotHostBackend extends HotSpotBackend implements HostBackend {
 
     /**
+     * Descriptor for {@link DeoptimizationStub#deoptimizationHandler}.
+     */
+    public static final ForeignCallDescriptor DEOPTIMIZATION_HANDLER = new ForeignCallDescriptor("deoptimizationHandler", void.class);
+
+    /**
+     * Descriptor for {@link UncommonTrapStub#uncommonTrapHandler}.
+     */
+    public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class);
+
+    /**
      * This will be 0 if stack banging is disabled.
      */
     protected final int pagesToBang;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Wed Apr 30 15:41:44 2014 -1000
@@ -24,8 +24,10 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.gen.*;
 
@@ -43,21 +45,87 @@
      */
     void emitTailcall(Value[] args, Value address);
 
-    void emitLeaveCurrentStackFrame();
-
-    void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo);
+    void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason);
 
-    void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp);
-
-    void emitLeaveUnpackFramesStackFrame();
-
+    /**
+     * Emits code for a {@link SaveAllRegistersNode}.
+     *
+     * @return a {@link SaveRegistersOp} operation
+     */
     SaveRegistersOp emitSaveAllRegisters();
 
-    void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason);
+    /**
+     * Emits code for a {@link LeaveCurrentStackFrameNode}.
+     *
+     * @param saveRegisterOp saved registers
+     */
+    default void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    /**
+     * Emits code for a {@link LeaveDeoptimizedStackFrameNode}.
+     *
+     * @param frameSize
+     * @param initialInfo
+     */
+    default void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    /**
+     * Emits code for a {@link EnterUnpackFramesStackFrameNode}.
+     *
+     * @param framePc
+     * @param senderSp
+     * @param senderFp
+     * @param saveRegisterOp
+     */
+    default void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) {
+        throw GraalInternalError.unimplemented();
+    }
 
-    void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo);
+    /**
+     * Emits code for a {@link LeaveUnpackFramesStackFrameNode}.
+     *
+     * @param saveRegisterOp
+     */
+    default void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    /**
+     * Emits code for a {@link PushInterpreterFrameNode}.
+     *
+     * @param frameSize
+     * @param framePc
+     * @param senderSp
+     * @param initialInfo
+     */
+    default void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) {
+        throw GraalInternalError.unimplemented();
+    }
 
-    Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp);
+    /**
+     * Emits code for a {@link UncommonTrapCallNode}.
+     *
+     * @param trapRequest
+     * @param saveRegisterOp
+     * @return a {@code Deoptimization::UnrollBlock} pointer
+     */
+    default Value emitUncommonTrapCall(Value trapRequest, SaveRegistersOp saveRegisterOp) {
+        throw GraalInternalError.unimplemented();
+    }
+
+    /**
+     * Emits code for a {@link DeoptimizationFetchUnrollInfoCallNode}.
+     *
+     * @param saveRegisterOp
+     * @return a {@code Deoptimization::UnrollBlock} pointer
+     */
+    default Value emitDeoptimizationFetchUnrollInfoCall(SaveRegistersOp saveRegisterOp) {
+        throw GraalInternalError.unimplemented();
+    }
 
     /**
      * Gets a stack slot for a lock at a given lock nesting depth.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Apr 30 15:41:44 2014 -1000
@@ -1353,8 +1353,6 @@
         return unsafe.getAddress(codeCacheHeap + codeHeapMemoryOffset + virtualSpaceHighBoundaryOffset);
     }
 
-    @Stable public long handleDeoptStub;
-
     @HotSpotVMField(name = "StubRoutines::_aescrypt_encryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptEncryptBlockStub;
     @HotSpotVMField(name = "StubRoutines::_aescrypt_decryptBlock", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long aescryptDecryptBlockStub;
     @HotSpotVMField(name = "StubRoutines::_cipherBlockChaining_encryptAESCrypt", type = "address", get = HotSpotVMField.Type.VALUE) @Stable public long cipherBlockChainingEncryptAESCryptStub;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Wed Apr 30 15:41:44 2014 -1000
@@ -103,7 +103,6 @@
     public void initialize(HotSpotProviders providers, HotSpotVMConfig c) {
         TargetDescription target = providers.getCodeCache().getTarget();
 
-        registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub(), NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
 
         registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java	Wed Apr 30 15:41:44 2014 -1000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, 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.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.word.*;
+
+/**
+ * A call to the runtime code {@code Deoptimization::fetch_unroll_info}.
+ */
+@NodeInfo(allowedUsageTypes = {InputType.Memory})
+public class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi {
+
+    @Input private SaveAllRegistersNode registerSaver;
+    private final ForeignCallsProvider foreignCalls;
+    public static final ForeignCallDescriptor FETCH_UNROLL_INFO = new ForeignCallDescriptor("fetchUnrollInfo", Word.class, Word.class);
+
+    public DeoptimizationFetchUnrollInfoCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver) {
+        super(StampFactory.forKind(Kind.fromJavaClass(FETCH_UNROLL_INFO.getResultType())));
+        this.registerSaver = (SaveAllRegistersNode) registerSaver;
+        this.foreignCalls = foreignCalls;
+    }
+
+    @Override
+    public LocationIdentity[] getLocationIdentities() {
+        return foreignCalls.getKilledLocations(FETCH_UNROLL_INFO);
+    }
+
+    public SaveRegistersOp getSaveRegistersOp() {
+        return registerSaver.getSaveRegistersOp();
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitDeoptimizationFetchUnrollInfoCall(getSaveRegistersOp());
+        gen.setResult(this, result);
+    }
+
+    @NodeIntrinsic
+    public static native Word fetchUnrollInfo(long registerSaver);
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return null;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EnterUnpackFramesStackFrameNode.java	Wed Apr 30 15:41:44 2014 -1000
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.word.*;
@@ -39,12 +40,18 @@
     @Input private ValueNode framePc;
     @Input private ValueNode senderSp;
     @Input private ValueNode senderFp;
+    @Input private SaveAllRegistersNode registerSaver;
 
-    public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp) {
+    public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) {
         super(StampFactory.forVoid());
         this.framePc = framePc;
         this.senderSp = senderSp;
         this.senderFp = senderFp;
+        this.registerSaver = (SaveAllRegistersNode) registerSaver;
+    }
+
+    private SaveRegistersOp getSaveRegistersOp() {
+        return registerSaver.getSaveRegistersOp();
     }
 
     @Override
@@ -52,9 +59,9 @@
         Value operandValue = gen.operand(framePc);
         Value senderSpValue = gen.operand(senderSp);
         Value senderFpValue = gen.operand(senderFp);
-        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitEnterUnpackFramesStackFrame(operandValue, senderSpValue, senderFpValue);
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitEnterUnpackFramesStackFrame(operandValue, senderSpValue, senderFpValue, getSaveRegistersOp());
     }
 
     @NodeIntrinsic
-    public static native void enterUnpackFramesStackFrame(Word framePc, Word senderSp, Word senderFp);
+    public static native void enterUnpackFramesStackFrame(Word framePc, Word senderSp, Word senderFp, long registerSaver);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveCurrentStackFrameNode.java	Wed Apr 30 15:41:44 2014 -1000
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -33,15 +34,22 @@
  */
 public class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable {
 
-    public LeaveCurrentStackFrameNode() {
+    @Input private SaveAllRegistersNode registerSaver;
+
+    public LeaveCurrentStackFrameNode(ValueNode registerSaver) {
         super(StampFactory.forVoid());
+        this.registerSaver = (SaveAllRegistersNode) registerSaver;
+    }
+
+    private SaveRegistersOp getSaveRegistersOp() {
+        return registerSaver.getSaveRegistersOp();
     }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveCurrentStackFrame();
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveCurrentStackFrame(getSaveRegistersOp());
     }
 
     @NodeIntrinsic
-    public static native void leaveCurrentStackFrame();
+    public static native void leaveCurrentStackFrame(long registerSaver);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java	Wed Apr 30 15:41:44 2014 -1000
@@ -25,6 +25,7 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -34,15 +35,22 @@
  */
 public class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable {
 
-    public LeaveUnpackFramesStackFrameNode() {
+    @Input private SaveAllRegistersNode registerSaver;
+
+    public LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) {
         super(StampFactory.forVoid());
+        this.registerSaver = (SaveAllRegistersNode) registerSaver;
+    }
+
+    private SaveRegistersOp getSaveRegistersOp() {
+        return registerSaver.getSaveRegistersOp();
     }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveUnpackFramesStackFrame();
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveUnpackFramesStackFrame(getSaveRegistersOp());
     }
 
     @NodeIntrinsic
-    public static native void leaveUnpackFramesStackFrame();
+    public static native void leaveUnpackFramesStackFrame(long registerSaver);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Wed Apr 30 15:09:15 2014 -1000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java	Wed Apr 30 15:41:44 2014 -1000
@@ -45,30 +45,35 @@
  *
  * The steps taken by this frame are as follows:
  *
- * - push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all potentially
- * live registers (at a pollpoint many registers can be live).
+ * <li>push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all
+ * potentially live registers (at a pollpoint many registers can be live).
  *
- * - call the C routine: Deoptimization::fetch_unroll_info (this function returns information about
- * the number and size of interpreter frames which are equivalent to the frame which is being
+ * <li>call the C routine: Deoptimization::fetch_unroll_info (this function returns information
+ * about the number and size of interpreter frames which are equivalent to the frame which is being
  * deoptimized)
  *
- * - deallocate the unpack frame, restoring only results values. Other volatile registers will now
+ * <li>deallocate the unpack frame, restoring only results values. Other volatile registers will now
  * be captured in the vframeArray as needed.
  *
- * - deallocate the deoptimization frame
+ * <li>deallocate the deoptimization frame
  *
- * - in a loop using the information returned in the previous step push new interpreter frames (take
- * care to propagate the return values through each new frame pushed)
+ * <li>in a loop using the information returned in the previous step push new interpreter frames
+ * (take care to propagate the return values through each new frame pushed)
  *
- * - create a dummy "unpack_frame" and save the return values (O0, O1, F0)
+ * <li>create a dummy "unpack_frame" and save the return values (O0, O1, F0)
  *
- * - call the C routine: Deoptimization::unpack_frames (this function lays out values on the
+ * <li>call the C routine: Deoptimization::unpack_frames (this function lays out values on the
  * interpreter frame which was just created)
  *
- * - deallocate the dummy unpack_frame
+ * <li>deallocate the dummy unpack_frame
+ *
+ * <li>ensure that all the return values are correctly set and then do a return to the interpreter
+ * entry point
  *
- * - ensure that all the return values are correctly set and then do a return to the interpreter
- * entry point
+ * <p>
+ * <b>ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet
+ * because we change the current stack layout and so the code is very sensitive to register
+ * allocation.</b>
  */
 public class DeoptimizationStub extends SnippetStub {
 
@@ -97,31 +102,15 @@
     }
 
     /**
-     * Uncommon trap.
-     *
-     * We save the argument return registers. We call the first C routine, fetch_unroll_info(). This
-     * routine captures the return values and returns a structure which describes the current frame
-     * size and the sizes of all replacement frames. The current frame is compiled code and may
-     * contain many inlined functions, each with their own JVM state. We pop the current frame, then
-     * push all the new frames. Then we call the C routine unpack_frames() to populate these frames.
-     * Finally unpack_frames() returns us the new target address. Notice that callee-save registers
-     * are BLOWN here; they have already been captured in the vframeArray at the time the return PC
-     * was patched.
-     *
-     * <p>
-     * <b>ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet
-     * because we change the current stack layout and so the code is very sensitive to register
-     * allocation.</b>
+     * Deoptimization handler for normal deoptimization
+     * {@link HotSpotVMConfig#deoptimizationUnpackDeopt}.
      */
     @Snippet
-    private static void uncommonTrapHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) {
+    private static void deoptimizationHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) {
         final Word thread = registerAsWord(threadRegister);
-        long registerSaver = SaveAllRegistersNode.saveAllRegisters();
+        final long registerSaver = SaveAllRegistersNode.saveAllRegisters();
 
-        final int actionAndReason = readPendingDeoptimization(thread);
-        writePendingDeoptimization(thread, -1);
-
-        final Word unrollBlock = UncommonTrapCallNode.uncommonTrap(registerSaver, actionAndReason);
+        final Word unrollBlock = DeoptimizationFetchUnrollInfoCallNode.fetchUnrollInfo(registerSaver);
 
         // Pop all the frames we must move/replace.
         //
@@ -131,7 +120,7 @@
         // 3: caller of deoptimizing frame (could be compiled/interpreted).
 
         // Pop self-frame.
-        LeaveCurrentStackFrameNode.leaveCurrentStackFrame();
+        LeaveCurrentStackFrameNode.leaveCurrentStackFrame(registerSaver);
 
         // Load the initial info we should save (e.g. frame pointer).
         final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset());
@@ -193,13 +182,13 @@
          * unknown alignment we need to align it here before calling C++ code.
          */
         final Word senderFp = initialInfo;
-        EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp);
+        EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp, registerSaver);
 
-        // Pass uncommon trap mode to unpack frames.
-        final int mode = deoptimizationUnpackUncommonTrap();
+        // Pass unpack deopt mode to unpack frames.
+        final int mode = deoptimizationUnpackDeopt();
         unpackFrames(UNPACK_FRAMES, thread, mode);
 
-        LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame();
+        LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame(registerSaver);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java	Wed Apr 30 15:41:44 2014 -1000
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2013, 2014, 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.stubs;
+
+import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.hotspot.stubs.StubUtil.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.word.*;
+
+/**
+ * Uncommon trap stub.
+ *
+ * This is the entry point for code which is returning to a de-optimized frame.
+ *
+ * The steps taken by this frame are as follows:
+ *
+ * <li>push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all
+ * potentially live registers (at a pollpoint many registers can be live).
+ *
+ * <li>call the C routine: Deoptimization::fetch_unroll_info (this function returns information
+ * about the number and size of interpreter frames which are equivalent to the frame which is being
+ * deoptimized)
+ *
+ * <li>deallocate the unpack frame, restoring only results values. Other volatile registers will now
+ * be captured in the vframeArray as needed.
+ *
+ * <li>deallocate the deoptimization frame
+ *
+ * <li>in a loop using the information returned in the previous step push new interpreter frames
+ * (take care to propagate the return values through each new frame pushed)
+ *
+ * <li>create a dummy "unpack_frame" and save the return values (O0, O1, F0)
+ *
+ * <li>call the C routine: Deoptimization::unpack_frames (this function lays out values on the
+ * interpreter frame which was just created)
+ *
+ * <li>deallocate the dummy unpack_frame
+ *
+ * <li>ensure that all the return values are correctly set and then do a return to the interpreter
+ * entry point
+ *
+ * <p>
+ * <b>ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet
+ * because we change the current stack layout and so the code is very sensitive to register
+ * allocation.</b>
+ */
+public class UncommonTrapStub extends SnippetStub {
+
+    private final TargetDescription target;
+
+    public UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) {
+        super(providers, target, linkage);
+        this.target = target;
+    }
+
+    @Override
+    public boolean preservesRegisters() {
+        return false;
+    }
+
+    @Override
+    protected Object getConstantParameterValue(int index, String name) {
+        switch (index) {
+            case 0:
+                return providers.getRegisters().getThreadRegister();
+            case 1:
+                return providers.getRegisters().getStackPointerRegister();
+            default:
+                throw GraalInternalError.shouldNotReachHere("unknown parameter " + name + " at index " + index);
+        }
+    }
+
+    /**
+     * Uncommon trap handler.
+     *
+     * We save the argument return registers. We call the first C routine, fetch_unroll_info(). This
+     * routine captures the return values and returns a structure which describes the current frame
+     * size and the sizes of all replacement frames. The current frame is compiled code and may
+     * contain many inlined functions, each with their own JVM state. We pop the current frame, then
+     * push all the new frames. Then we call the C routine unpack_frames() to populate these frames.
+     * Finally unpack_frames() returns us the new target address. Notice that callee-save registers
+     * are BLOWN here; they have already been captured in the vframeArray at the time the return PC
+     * was patched.
+     */
+    @Snippet
+    private static void uncommonTrapHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) {
+        final Word thread = registerAsWord(threadRegister);
+        final long registerSaver = SaveAllRegistersNode.saveAllRegisters();
+
+        final int actionAndReason = readPendingDeoptimization(thread);
+        writePendingDeoptimization(thread, -1);
+
+        final Word unrollBlock = UncommonTrapCallNode.uncommonTrap(registerSaver, actionAndReason);
+
+        // Pop all the frames we must move/replace.
+        //
+        // Frame picture (youngest to oldest)
+        // 1: self-frame
+        // 2: deoptimizing frame
+        // 3: caller of deoptimizing frame (could be compiled/interpreted).
+
+        // Pop self-frame.
+        LeaveCurrentStackFrameNode.leaveCurrentStackFrame(registerSaver);
+
+        // Load the initial info we should save (e.g. frame pointer).
+        final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset());
+
+        // Pop deoptimized frame.
+        final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset());
+        LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo);
+
+        /*
+         * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for
+         * total size of the interpreter frames plus shadow page size. Bang one page at a time
+         * because large sizes can bang beyond yellow and red zones.
+         * 
+         * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository.
+         */
+        final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset());
+        final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages();
+        Word stackPointer = readRegister(stackPointerRegister);
+
+        for (int i = 1; i < bangPages; i++) {
+            stackPointer.writeInt((-i * pageSize()) + stackBias(), 0);
+        }
+
+        // Load number of interpreter frames.
+        final int numberOfFrames = unrollBlock.readInt(deoptimizationUnrollBlockNumberOfFramesOffset());
+
+        // Load address of array of frame sizes.
+        final Word frameSizes = unrollBlock.readWord(deoptimizationUnrollBlockFrameSizesOffset());
+
+        // Load address of array of frame PCs.
+        final Word framePcs = unrollBlock.readWord(deoptimizationUnrollBlockFramePcsOffset());
+
+        /*
+         * Get the current stack pointer (sender's original SP) before adjustment so that we can
+         * save it in the skeletal interpreter frame.
+         */
+        Word senderSp = readRegister(stackPointerRegister);
+
+        // Adjust old interpreter frame to make space for new frame's extra Java locals.
+        final int callerAdjustment = unrollBlock.readInt(deoptimizationUnrollBlockCallerAdjustmentOffset());
+        writeRegister(stackPointerRegister, readRegister(stackPointerRegister).subtract(callerAdjustment));
+
+        for (int i = 0; i < numberOfFrames; i++) {
+            final Word frameSize = frameSizes.readWord(i * wordSize());
+            final Word framePc = framePcs.readWord(i * wordSize());
+
+            // Push an interpreter frame onto the stack.
+            PushInterpreterFrameNode.pushInterpreterFrame(frameSize, framePc, senderSp, initialInfo);
+
+            // Get the current stack pointer (sender SP) and pass it to next frame.
+            senderSp = readRegister(stackPointerRegister);
+        }
+
+        // Get final return address.
+        final Word framePc = framePcs.readWord(numberOfFrames * wordSize());
+
+        /*
+         * Enter a frame to call out to unpack frames. Since we changed the stack pointer to an
+         * unknown alignment we need to align it here before calling C++ code.
+         */
+        final Word senderFp = initialInfo;
+        EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp, registerSaver);
+
+        // Pass uncommon trap mode to unpack frames.
+        final int mode = deoptimizationUnpackUncommonTrap();
+        unpackFrames(UNPACK_FRAMES, thread, mode);
+
+        LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame(registerSaver);
+    }
+
+    /**
+     * Reads the value of the passed register as a Word.
+     */
+    private static Word readRegister(Register register) {
+        return registerAsWord(register, false, false);
+    }
+
+    /**
+     * Writes the value of the passed register.
+     *
+     * @param value value the register should be set to
+     */
+    private static void writeRegister(Register register, Word value) {
+        writeRegisterAsWord(register, value);
+    }
+
+    @Fold
+    private static int stackShadowPages() {
+        return config().useStackBanging ? config().stackShadowPages : 0;
+    }
+
+    /**
+     * Returns the stack bias for the host architecture.
+     *
+     * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository.
+     *
+     * @return stack bias
+     */
+    @Deprecated
+    @Fold
+    private static int stackBias() {
+        return config().stackBias;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() {
+        return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockCallerAdjustmentOffset() {
+        return config().deoptimizationUnrollBlockCallerAdjustmentOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockNumberOfFramesOffset() {
+        return config().deoptimizationUnrollBlockNumberOfFramesOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockTotalFrameSizesOffset() {
+        return config().deoptimizationUnrollBlockTotalFrameSizesOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockFrameSizesOffset() {
+        return config().deoptimizationUnrollBlockFrameSizesOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockFramePcsOffset() {
+        return config().deoptimizationUnrollBlockFramePcsOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnrollBlockInitialInfoOffset() {
+        return config().deoptimizationUnrollBlockInitialInfoOffset;
+    }
+
+    @Fold
+    private static int deoptimizationUnpackDeopt() {
+        return config().deoptimizationUnpackDeopt;
+    }
+
+    @Fold
+    private static int deoptimizationUnpackUncommonTrap() {
+        return config().deoptimizationUnpackUncommonTrap;
+    }
+
+    public static final ForeignCallDescriptor UNPACK_FRAMES = descriptorFor(UncommonTrapStub.class, "unpackFrames");
+
+    @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true)
+    public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode);
+}
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Apr 30 15:09:15 2014 -1000
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Apr 30 15:41:44 2014 -1000
@@ -156,8 +156,6 @@
 
   //------------------------------------------------------------------------------------------------
 
-  set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
-
   set_address("registerFinalizerAddress", SharedRuntime::register_finalizer);
   set_address("exceptionHandlerForReturnAddressAddress", SharedRuntime::exception_handler_for_return_address);
   set_address("osrMigrationEndAddress", SharedRuntime::OSR_migration_end);
--- a/src/share/vm/runtime/deoptimization.cpp	Wed Apr 30 15:09:15 2014 -1000
+++ b/src/share/vm/runtime/deoptimization.cpp	Wed Apr 30 15:41:44 2014 -1000
@@ -359,7 +359,8 @@
 #ifdef ASSERT
   assert(cb->is_deoptimization_stub() ||
          cb->is_uncommon_trap_stub() ||
-         strcmp("Stub<DeoptimizationStub.uncommonTrapHandler>", cb->name()) == 0,
+         strcmp("Stub<DeoptimizationStub.deoptimizationHandler>", cb->name()) == 0 ||
+         strcmp("Stub<UncommonTrapStub.uncommonTrapHandler>", cb->name()) == 0,
          err_msg("unexpected code blob: %s", cb->name()));
 #endif
 #else