changeset 9348:927e0792094b

Merge.
author Christian Humer <christian.humer@gmail.com>
date Fri, 26 Apr 2013 23:03:09 +0200
parents f43d04388815 (current diff) 430707bc6f58 (diff)
children 0fccad3ce40d 86d981cd8e22
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java
diffstat 47 files changed, 1154 insertions(+), 254 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeUtil.java	Fri Apr 26 23:03:09 2013 +0200
@@ -303,6 +303,14 @@
             }
             sb.append(' ').append(bm).append(nl);
         }
+        RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
+        if (calleeSaveInfo != null) {
+            sb.append("callee-save-info:").append(nl);
+            Map<Integer, Register> map = calleeSaveInfo.slotsToRegisters(true);
+            for (Map.Entry<Integer, Register> e : map.entrySet()) {
+                sb.append("    ").append(e.getValue()).append(" -> ").append(formatter.formatStackSlot(e.getKey())).append(nl);
+            }
+        }
         BytecodeFrame frame = info.frame();
         if (frame != null) {
             append(sb, frame);
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java	Fri Apr 26 23:03:09 2013 +0200
@@ -507,6 +507,16 @@
         if (info != null) {
             appendRefMap(sb, "stackMap", info.getFrameRefMap());
             appendRefMap(sb, "registerMap", info.getRegisterRefMap());
+            RegisterSaveLayout calleeSaveInfo = info.getCalleeSaveInfo();
+            if (calleeSaveInfo != null) {
+                sb.append(" callee-save-info[");
+                String sep = "";
+                for (Map.Entry<Register, Integer> e : calleeSaveInfo.registersToSlots(true).entrySet()) {
+                    sb.append(sep).append(e.getKey()).append("->").append(e.getValue());
+                    sep = ", ";
+                }
+                sb.append(']');
+            }
             BytecodePosition codePos = info.getBytecodePosition();
             if (codePos != null) {
                 MetaUtil.appendLocation(sb.append(" "), codePos.getMethod(), codePos.getBCI());
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Fri Apr 26 23:03:09 2013 +0200
@@ -26,8 +26,16 @@
 import java.util.*;
 
 /**
- * Represents the debugging information for a particular place in the code, which includes the code
- * position, a reference map, and deoptimization information.
+ * Represents the debugging information for a particular point of execution. This information
+ * includes:
+ * <ul>
+ * <li>a {@linkplain #getBytecodePosition() bytecode position}</li>
+ * <li>a reference map for {@linkplain #getRegisterRefMap() registers}</li>
+ * <li>a reference map for {@linkplain #getRegisterRefMap() stack slots} in the current frame</li>
+ * <li>a map from bytecode locals and operand stack slots to their values or locations from which
+ * their values can be read</li>
+ * <li>a map from the registers (in the caller's frame) to the slots where they are saved in the
+ * current frame</li>
  */
 public class DebugInfo implements Serializable {
 
@@ -37,6 +45,7 @@
     private final BitSet registerRefMap;
     private final BitSet frameRefMap;
     private final short deoptimizationReason;
+    private RegisterSaveLayout calleeSaveInfo;
 
     /**
      * Creates a new {@link DebugInfo} from the given values.
@@ -125,4 +134,20 @@
     public short getDeoptimizationReason() {
         return deoptimizationReason;
     }
+
+    /**
+     * Sets the map from the registers (in the caller's frame) to the slots where they are saved in
+     * the current frame.
+     */
+    public void setCalleeSaveInfo(RegisterSaveLayout calleeSaveInfo) {
+        this.calleeSaveInfo = calleeSaveInfo;
+    }
+
+    /**
+     * Gets the map from the registers (in the caller's frame) to the slots where they are saved in
+     * the current frame. If no such information is available, {@code null} is returned.
+     */
+    public RegisterSaveLayout getCalleeSaveInfo() {
+        return calleeSaveInfo;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RegisterSaveLayout.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 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.api.code;
+
+import java.util.*;
+
+/**
+ * A map from registers to frame slots. This can be used to describe where callee saved registers
+ * are saved in a callee's frame.
+ */
+public class RegisterSaveLayout {
+
+    /**
+     * Keys.
+     */
+    private Register[] registers;
+
+    /**
+     * Slot indexes relative to stack pointer.
+     */
+    private int[] slots;
+
+    /**
+     * Creates a map from registers to frame slots.
+     * 
+     * @param registers the keys in the map
+     * @param slots frame slot index for each register in {@code registers}
+     */
+    public RegisterSaveLayout(Register[] registers, int[] slots) {
+        assert registers.length == slots.length;
+        this.registers = registers;
+        this.slots = slots;
+        assert registersToSlots(false).size() == registers.length : "non-unique registers";
+        assert new HashSet<>(registersToSlots(false).values()).size() == slots.length : "non-unqiue slots";
+    }
+
+    /**
+     * Gets this layout information as a {@link Map} from registers to slots.
+     */
+    public Map<Register, Integer> registersToSlots(boolean sorted) {
+        Map<Register, Integer> result;
+        if (sorted) {
+            result = new TreeMap<>();
+        } else {
+            result = new HashMap<>();
+        }
+        for (int i = 0; i < registers.length; i++) {
+            result.put(registers[i], slots[i]);
+        }
+        return result;
+    }
+
+    /**
+     * Gets this layout information as a {@link Map} from slots to registers.
+     */
+    public Map<Integer, Register> slotsToRegisters(boolean sorted) {
+        Map<Integer, Register> result;
+        if (sorted) {
+            result = new TreeMap<>();
+        } else {
+            result = new HashMap<>();
+        }
+        for (int i = 0; i < registers.length; i++) {
+            result.put(slots[i], registers[i]);
+        }
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return registersToSlots(true).toString();
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Apr 26 23:03:09 2013 +0200
@@ -45,6 +45,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.ParametersOp;
 import com.oracle.graal.lir.LIRInstruction.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
@@ -161,28 +162,59 @@
 
         Stub stub = runtime().asStub(lirGen.method());
         if (stub != null) {
-            final Set<Register> definedRegisters = new HashSet<>();
-            ValueProcedure defProc = new ValueProcedure() {
+
+            List<AMD64RegisterPreservationOp> registerPreservations = new ArrayList<>();
+            final Set<Register> definedRegisters = gatherDefinedRegisters(lir, registerPreservations);
+            stub.initDefinedRegisters(definedRegisters);
+
+            // Eliminate unnecessary register preservation
+            for (AMD64RegisterPreservationOp op : registerPreservations) {
+                op.doNotPreserve(definedRegisters);
+            }
+
+            // Record where preserved registers are saved
+            for (Map.Entry<LIRFrameState, AMD64RestoreRegistersOp> e : gen.calleeSaveInfo.entrySet()) {
+                e.getValue().describePreservation(e.getKey().debugInfo(), frameMap);
+            }
+        }
+
+        return tasm;
+    }
 
-                @Override
-                public Value doValue(Value value) {
-                    if (ValueUtil.isRegister(value)) {
-                        final Register reg = ValueUtil.asRegister(value);
-                        definedRegisters.add(reg);
-                    }
-                    return value;
+    /**
+     * Finds all the registers that are defined by some given LIR.
+     * 
+     * @param lir the LIR to examine
+     * @param registerPreservations register preservation operations in {@code lir} are added to this list
+     * @return the registers that are defined by or used as temps for any instruction in {@code lir}
+     */
+    private static Set<Register> gatherDefinedRegisters(LIR lir, List<AMD64RegisterPreservationOp> registerPreservations) {
+        final Set<Register> definedRegisters = new HashSet<>();
+        ValueProcedure defProc = new ValueProcedure() {
+
+            @Override
+            public Value doValue(Value value) {
+                if (ValueUtil.isRegister(value)) {
+                    final Register reg = ValueUtil.asRegister(value);
+                    definedRegisters.add(reg);
                 }
-            };
-            for (Block block : lir.codeEmittingOrder()) {
-                for (LIRInstruction op : lir.lir(block)) {
+                return value;
+            }
+        };
+        for (Block block : lir.codeEmittingOrder()) {
+            for (LIRInstruction op : lir.lir(block)) {
+                if (op instanceof AMD64RegisterPreservationOp) {
+                    // Don't consider these ops as definitions
+                    registerPreservations.add((AMD64RegisterPreservationOp) op);
+                } else if (op instanceof ParametersOp) {
+                    // Don't consider these ops as definitions
+                } else {
                     op.forEachTemp(defProc);
                     op.forEachOutput(defProc);
                 }
             }
-            stub.initDefinedRegisters(definedRegisters);
         }
-
-        return tasm;
+        return definedRegisters;
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+@Opcode("CRUNTIME_CALL_EPILOGUE")
+final class AMD64HotSpotCRuntimeCallEpilogueOp extends AMD64LIRInstruction {
+
+    @Use({REG, ILLEGAL}) protected Value thread;
+
+    AMD64HotSpotCRuntimeCallEpilogueOp(Value thread) {
+        this.thread = thread;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        // reset last Java frame:
+        HotSpotVMConfig config = graalRuntime().getConfig();
+        masm.movslq(new AMD64Address(asRegister(thread), config.threadLastJavaSpOffset), 0);
+        masm.movslq(new AMD64Address(asRegister(thread), config.threadLastJavaFpOffset), 0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+@Opcode("CRUNTIME_CALL_PROLOGUE")
+final class AMD64HotSpotCRuntimeCallPrologueOp extends AMD64LIRInstruction {
+
+    @Use({REG, ILLEGAL}) protected Value thread;
+
+    AMD64HotSpotCRuntimeCallPrologueOp(Value thread) {
+        this.thread = thread;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+
+        // save last Java frame
+        masm.movq(new AMD64Address(asRegister(thread), graalRuntime().getConfig().threadLastJavaSpOffset), rsp);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.amd64;
+
+import static com.oracle.graal.amd64.AMD64.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.amd64.AMD64DeoptimizeOp.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Removes the current frame and tail calls the uncommon trap routine.
+ */
+@Opcode("DEOPT_CALLER")
+final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp {
+
+    private final DeoptimizationAction action;
+    private final DeoptimizationReason reason;
+
+    AMD64HotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) {
+        this.action = action;
+        this.reason = reason;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        if (isStackSlot(savedRbp)) {
+            // Restoring RBP from the stack must be done before the frame is removed
+            masm.movq(rbp, (AMD64Address) tasm.asAddress(savedRbp));
+        } else {
+            Register framePointer = asRegister(savedRbp);
+            if (framePointer != rbp) {
+                masm.movq(rbp, framePointer);
+            }
+        }
+        if (tasm.frameContext != null) {
+            tasm.frameContext.leave(tasm);
+        }
+        HotSpotGraalRuntime runtime = graalRuntime();
+        Register thread = runtime.getRuntime().threadRegister();
+        masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason));
+        AMD64Call.directJmp(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE));
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Apr 26 23:03:09 2013 +0200
@@ -145,8 +145,8 @@
             }
         }
         params[params.length - 1] = rbpParam;
+        ParametersOp paramsOp = new ParametersOp(params);
 
-        ParametersOp paramsOp = new ParametersOp(params);
         append(paramsOp);
 
         saveRbp = new SaveRbp(new PlaceholderOp(currentBlock, lir.lir(currentBlock).size()));
@@ -172,6 +172,74 @@
         return runtime().asStub(method) != null;
     }
 
+    /**
+     * Map from debug infos that need to be updated with callee save information to the operations
+     * that provide the information.
+     */
+    Map<LIRFrameState, AMD64RestoreRegistersOp> calleeSaveInfo = new HashMap<>();
+
+    private LIRFrameState currentRuntimeCallInfo;
+
+    @Override
+    protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
+        boolean needsCalleeSave = callTarget.getDescriptor() == NewArrayRuntimeCall.NEW_ARRAY_RUNTIME;
+        if (needsCalleeSave) {
+            currentRuntimeCallInfo = info;
+        }
+        super.emitCall(callTarget, result, arguments, temps, info);
+    }
+
+    @Override
+    public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args) {
+        boolean needsCalleeSave = callTarget.getDescriptor() == NewArrayRuntimeCall.NEW_ARRAY_RUNTIME;
+
+        RegisterValue[] savedRegisters = null;
+        StackSlot[] savedRegisterLocations = null;
+        if (needsCalleeSave) {
+            Register returnReg = isRegister(cc.getReturn()) ? asRegister(cc.getReturn()) : null;
+            Set<Register> registers = new HashSet<>(Arrays.asList(frameMap.registerConfig.getAllocatableRegisters()));
+            if (returnReg != null) {
+                registers.remove(returnReg);
+            }
+
+            savedRegisters = new RegisterValue[registers.size()];
+            savedRegisterLocations = new StackSlot[savedRegisters.length];
+            int savedRegisterIndex = 0;
+            for (Register reg : registers) {
+                assert reg.isCpu() || reg.isFpu();
+                savedRegisters[savedRegisterIndex++] = reg.asValue(reg.isCpu() ? Kind.Long : Kind.Double);
+            }
+
+            append(new ParametersOp(savedRegisters));
+            for (int i = 0; i < savedRegisters.length; i++) {
+                StackSlot spillSlot = frameMap.allocateSpillSlot(Kind.Long);
+                savedRegisterLocations[i] = spillSlot;
+            }
+            AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations);
+            append(save);
+
+            Value thread = args[0];
+            AMD64HotSpotCRuntimeCallPrologueOp op = new AMD64HotSpotCRuntimeCallPrologueOp(thread);
+            append(op);
+        }
+
+        Variable result = super.emitCall(callTarget, cc, info, args);
+
+        if (needsCalleeSave) {
+
+            Value thread = args[0];
+            AMD64HotSpotCRuntimeCallEpilogueOp op = new AMD64HotSpotCRuntimeCallEpilogueOp(thread);
+            append(op);
+
+            AMD64RestoreRegistersOp restore = new AMD64RestoreRegistersOp(savedRegisterLocations.clone(), savedRegisters.clone());
+            AMD64RestoreRegistersOp oldValue = calleeSaveInfo.put(currentRuntimeCallInfo, restore);
+            assert oldValue == null;
+            append(restore);
+        }
+
+        return result;
+    }
+
     @Override
     protected CallingConvention createCallingConvention() {
         Stub stub = runtime().asStub(method);
@@ -224,7 +292,6 @@
     @Override
     public void emitTailcall(Value[] args, Value address) {
         append(new AMD64TailcallOp(args, address));
-
     }
 
     @Override
@@ -265,6 +332,13 @@
     }
 
     @Override
+    public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
+        AMD64HotSpotDeoptimizeCallerOp op = new AMD64HotSpotDeoptimizeCallerOp(action, reason);
+        epilogueOps.add(op);
+        append(op);
+    }
+
+    @Override
     public void beforeRegisterAllocation() {
         boolean hasDebugInfo = lir.hasDebugInfo();
         AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Fri Apr 26 23:03:09 2013 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.lir.asm.*;
 
 /**
- * Performs an unwind to throw an exception.
+ * Returns from a function.
  */
 @Opcode("RETURN")
 final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Apr 26 23:03:09 2013 +0200
@@ -29,7 +29,7 @@
 import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
-import static com.oracle.graal.hotspot.nodes.NewArraySlowStubCall.*;
+import static com.oracle.graal.hotspot.nodes.NewArrayRuntimeCall.*;
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceSlowStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
@@ -110,11 +110,12 @@
                 /* arg0:    hub */ rdx.asValue(word),
                 /* arg1: length */ rbx.asValue(Kind.Int));
 
-        addRuntimeCall(NEW_ARRAY_SLOW, config.newArrayStub,
+        addRuntimeCall(NEW_ARRAY_RUNTIME, config.newArrayAddress,
                 /*        temps */ null,
                 /*          ret */ rax.asValue(Kind.Object),
-                /* arg0:    hub */ rdx.asValue(word),
-                /* arg1: length */ rbx.asValue(Kind.Int));
+                /* arg0: thread */ nativeCallingConvention(word,
+                /* arg1:    hub */                         word,
+                /* arg2: length */                         Kind.Int));
 
         addStubCall(NEW_INSTANCE,
                 /*          ret */ rax.asValue(Kind.Object),
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java	Fri Apr 26 23:03:09 2013 +0200
@@ -22,11 +22,17 @@
  */
 package com.oracle.graal.hotspot;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CompilationResult.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.code.CompilationResult.ExceptionHandler;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.replacements.*;
 
 /**
  * Augments a {@link CompilationResult} with HotSpot-specific information.
@@ -37,7 +43,12 @@
     public final CompilationResult comp;
     public final HotSpotResolvedJavaMethod method; // used only for methods
     public final int entryBCI; // used only for methods
-    public final String name; // used only for stubs
+
+    /**
+     * Name of the RuntimeStub to be installed for this compilation result. If null, then the
+     * compilation result will be installed as an nmethod.
+     */
+    public final String stubName;
 
     public final Site[] sites;
     public final ExceptionHandler[] exceptionHandlers;
@@ -46,7 +57,14 @@
         this.method = method;
         this.comp = comp;
         this.entryBCI = entryBCI;
-        this.name = null;
+
+        // Class stubClass = Stub.class;
+        Class stubClass = NewArrayStub.class;
+        if (graalRuntime().getRuntime().lookupJavaType(stubClass).isAssignableFrom(method.getDeclaringClass()) && method.getAnnotation(Snippet.class) != null) {
+            this.stubName = MetaUtil.format("%h.%n", method);
+        } else {
+            this.stubName = null;
+        }
 
         sites = getSortedSites(comp);
         if (comp.getExceptionHandlers() == null) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java	Fri Apr 26 23:03:09 2013 +0200
@@ -42,6 +42,8 @@
      */
     void emitTailcall(Value[] args, Value address);
 
+    void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason);
+
     void visitDirectCompareAndSwap(DirectCompareAndSwapNode x);
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Fri Apr 26 23:03:09 2013 +0200
@@ -179,6 +179,11 @@
     public int uninitializedIdentityHashCodeValue;
 
     /**
+     * Offset of the pending exception field.
+     */
+    public int pendingExceptionOffset;
+
+    /**
      * Offset of the pending deoptimization field.
      */
     public int pendingDeoptimizationOffset;
@@ -302,6 +307,10 @@
     public int threadTlabStartOffset;
     public int threadTlabSizeOffset;
     public int threadAllocatedBytesOffset;
+    public int threadLastJavaSpOffset;
+    public int threadLastJavaFpOffset;
+    public int threadLastJavaPcOffset;
+    public int threadObjectResultOffset;
     public int tlabRefillWasteLimitOffset;
     public int tlabRefillWasteIncrement;
     public int tlabAlignmentReserve;
@@ -372,6 +381,8 @@
     public long cipherBlockChainingEncryptAESCryptStub;
     public long cipherBlockChainingDecryptAESCryptStub;
 
+    public long newArrayAddress;
+
     public int deoptReasonNullCheck;
     public int deoptReasonRangeCheck;
     public int deoptReasonClassCheck;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Fri Apr 26 23:03:09 2013 +0200
@@ -194,20 +194,20 @@
 
     long getMaxCallTargetOffset(long stub);
 
-    String disassembleNMethod(long nmethod);
+    String disassembleCodeBlob(long codeBlob);
 
     /**
-     * Gets a copy of the machine code for an nmethod.
+     * Gets a copy of the machine code for a CodeBlob.
      * 
-     * @return the machine code for {@code nmethod} if it is valid, null otherwise
+     * @return the machine code for {@code codeBlob} if it is valid, null otherwise
      */
-    byte[] getCode(long nmethod);
+    byte[] getCode(long codeBlob);
 
     StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
-    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException;
+    Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nmethod) throws InvalidInstalledCodeException;
 
-    Object executeCompiledMethodVarargs(Object[] args, long nativeMethod) throws InvalidInstalledCodeException;
+    Object executeCompiledMethodVarargs(Object[] args, long nmethod) throws InvalidInstalledCodeException;
 
     int getVtableEntryOffset(long metaspaceMethod);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Fri Apr 26 23:03:09 2013 +0200
@@ -130,16 +130,16 @@
     public native long getMaxCallTargetOffset(long stub);
 
     @Override
-    public native String disassembleNMethod(long nmethod);
+    public native String disassembleCodeBlob(long codeBlob);
 
     @Override
-    public native byte[] getCode(long nmethod);
+    public native byte[] getCode(long codeBlob);
 
     @Override
     public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci);
 
     @Override
-    public native Object executeCompiledMethodVarargs(Object[] args, long nativeMethod);
+    public native Object executeCompiledMethodVarargs(Object[] args, long nmethod);
 
     @Override
     public native int getVtableEntryOffset(long metaspaceMethod);
@@ -172,16 +172,16 @@
     public native boolean isInstalledCodeValid(long nativeMethod);
 
     @Override
-    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException {
-        return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod);
+    public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nmethod) throws InvalidInstalledCodeException {
+        return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nmethod);
     }
 
     /**
-     * Direct call to the given nativeMethod with three object arguments and an object return value.
-     * This method does not have an implementation on the C++ side, but its entry points (from
+     * Direct call to the given nmethod with three object arguments and an object return value. This
+     * method does not have an implementation on the C++ side, but its entry points (from
      * interpreter and from compiled code) are directly pointing to a manually generated assembly
      * stub that does the necessary argument shuffling and a tail call via an indirect jump to the
      * verified entry point of the given native method.
      */
-    private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod);
+    private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nmethod);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java	Fri Apr 26 23:03:09 2013 +0200
@@ -43,8 +43,9 @@
     private final HotSpotResolvedJavaMethod method;
     private final boolean isDefault;
     private final Graph graph;
-    long nmethod;
+    long codeBlob;
     long start;
+    boolean isNmethod;
 
     public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) {
         this.method = method;
@@ -56,8 +57,8 @@
         return isDefault;
     }
 
-    public long getMethodAddress() {
-        return nmethod;
+    public long getCodeBlob() {
+        return codeBlob;
     }
 
     public Graph getGraph() {
@@ -71,26 +72,29 @@
 
     @Override
     public boolean isValid() {
-        return graalRuntime().getCompilerToVM().isInstalledCodeValid(nmethod);
+        return !isNmethod || graalRuntime().getCompilerToVM().isInstalledCodeValid(codeBlob);
     }
 
     @Override
     public void invalidate() {
-        graalRuntime().getCompilerToVM().invalidateInstalledCode(nmethod);
+        if (isNmethod) {
+            graalRuntime().getCompilerToVM().invalidateInstalledCode(codeBlob);
+        }
     }
 
     @Override
     public String toString() {
-        return String.format("InstalledCode[method=%s, nmethod=0x%x]", method, nmethod);
+        return String.format("InstalledCode[method=%s, codeBlob=0x%x]", method, codeBlob);
     }
 
     @Override
     public Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException {
+        assert isNmethod;
         assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3;
         assert method.getSignature().getParameterKind(0) == Kind.Object;
         assert method.getSignature().getParameterKind(1) == Kind.Object;
         assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object;
-        return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod);
+        return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, codeBlob);
     }
 
     private boolean checkArgs(Object... args) {
@@ -109,8 +113,9 @@
 
     @Override
     public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
+        assert isNmethod;
         assert checkArgs(args);
-        return graalRuntime().getCompilerToVM().executeCompiledMethodVarargs(args, nmethod);
+        return graalRuntime().getCompilerToVM().executeCompiledMethodVarargs(args, codeBlob);
     }
 
     @Override
@@ -120,6 +125,6 @@
 
     @Override
     public byte[] getCode() {
-        return graalRuntime().getCompilerToVM().getCode(nmethod);
+        return graalRuntime().getCompilerToVM().getCode(codeBlob);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Fri Apr 26 23:03:09 2013 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.hotspot.meta;
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
-import static com.oracle.graal.graph.FieldIntrospection.*;
+import static com.oracle.graal.graph.UnsafeAccess.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.annotation.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Apr 26 23:03:09 2013 +0200
@@ -33,6 +33,7 @@
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
+import static com.oracle.graal.hotspot.stubs.Stub.*;
 import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*;
 import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*;
 import static com.oracle.graal.replacements.Log.*;
@@ -262,7 +263,7 @@
                         /* arg2:     value */                       Kind.Long,
                         /* arg3:     value */                       Kind.Long));
 
-        addRuntimeCall(Stub.STUB_PRINTF, config.stubPrintfStub,
+        addRuntimeCall(STUB_PRINTF, config.stubPrintfStub,
                         /*           temps */ null,
                         /*             ret */ ret(Kind.Void),
                         /* arg0:    format */ javaCallingConvention(Kind.Long,
@@ -951,8 +952,8 @@
 
     public String disassemble(InstalledCode code) {
         if (code.isValid()) {
-            long nmethod = ((HotSpotInstalledCode) code).getMethodAddress();
-            return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod);
+            long codeBlob = ((HotSpotInstalledCode) code).getCodeBlob();
+            return graalRuntime.getCompilerToVM().disassembleCodeBlob(codeBlob);
         }
         return null;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009, 2011, 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.graph.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Removes the current frame and tail calls the uncommon trap routine.
+ */
+@NodeInfo(shortName = "DeoptCaller", nameTemplate = "DeoptCaller {p#reason/s}")
+public class DeoptimizeCallerNode extends ControlSinkNode implements LIRLowerable {
+
+    private final DeoptimizationAction action;
+    private final DeoptimizationReason reason;
+
+    public DeoptimizeCallerNode(DeoptimizationAction action, DeoptimizationReason reason) {
+        super(StampFactory.forVoid());
+        this.action = action;
+        this.reason = reason;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        ((HotSpotLIRGenerator) gen).emitDeoptimizeCaller(action, reason);
+    }
+
+    @NodeIntrinsic
+    public static native void deopt(@ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter DeoptimizationReason reason);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java	Fri Apr 26 23:03:09 2013 +0200
@@ -69,11 +69,11 @@
         ResolvedJavaMethod method = null;
         ResolvedJavaField methodField = null;
         ResolvedJavaField metaspaceMethodField = null;
-        ResolvedJavaField nmethodField = null;
+        ResolvedJavaField codeBlobField = null;
         try {
             method = tool.lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class));
             methodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("method"));
-            nmethodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("nmethod"));
+            codeBlobField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("codeBlob"));
             metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod"));
         } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) {
             throw new IllegalStateException(e);
@@ -86,8 +86,8 @@
 
         StructuredGraph g = (StructuredGraph) graph();
 
-        LoadFieldNode loadnmethod = g.add(new LoadFieldNode(code, nmethodField));
-        UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadnmethod, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), graalRuntime().getTarget().wordKind));
+        LoadFieldNode loadCodeBlob = g.add(new LoadFieldNode(code, codeBlobField));
+        UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadCodeBlob, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), graalRuntime().getTarget().wordKind));
 
         LoadFieldNode loadMethod = g.add(new LoadFieldNode(code, methodField));
         LoadFieldNode loadmetaspaceMethod = g.add(new LoadFieldNode(loadMethod, metaspaceMethodField));
@@ -102,7 +102,7 @@
         g.addBeforeFixed(invoke, loadmetaspaceMethod);
         g.addBeforeFixed(loadmetaspaceMethod, loadMethod);
         g.addBeforeFixed(invoke, load);
-        g.addBeforeFixed(load, loadnmethod);
+        g.addBeforeFixed(load, loadCodeBlob);
 
         return invoke;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayRuntimeCall.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+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.word.*;
+
+/**
+ * Node implementing a call to the {@code new_array} stub.
+ */
+public class NewArrayRuntimeCall extends DeoptimizingStubCall implements LIRGenLowerable {
+
+    private static final Stamp defaultStamp = StampFactory.objectNonNull();
+
+    @Input private final ValueNode thread;
+    @Input private final ValueNode hub;
+    @Input private final ValueNode length;
+
+    public static final Descriptor NEW_ARRAY_RUNTIME = new Descriptor("new_array_runtime", false, Object.class, Word.class, Word.class, int.class);
+
+    public NewArrayRuntimeCall(ValueNode thread, ValueNode hub, ValueNode length) {
+        super(defaultStamp);
+        this.thread = thread;
+        this.hub = hub;
+        this.length = length;
+    }
+
+    @Override
+    public boolean inferStamp() {
+        if (stamp() == defaultStamp && hub.isConstant()) {
+            updateStamp(StampFactory.exactNonNull(HotSpotResolvedObjectType.fromMetaspaceKlass(hub.asConstant())));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void generate(LIRGenerator gen) {
+        RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY_RUNTIME);
+        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(thread), gen.operand(hub), gen.operand(length));
+        gen.setResult(this, result);
+    }
+
+    @NodeIntrinsic
+    public static native Object call(Word thread, Word hub, int length);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java	Fri Apr 26 22:44:05 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.nodes;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-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.word.*;
-
-/**
- * Node implementing a call to the {@code new_array} stub.
- */
-public class NewArraySlowStubCall extends DeoptimizingStubCall implements LIRGenLowerable {
-
-    private static final Stamp defaultStamp = StampFactory.objectNonNull();
-
-    @Input private final ValueNode hub;
-    @Input private final ValueNode length;
-
-    public static final Descriptor NEW_ARRAY_SLOW = new Descriptor("new_array_slow", false, Object.class, Word.class, int.class);
-
-    public NewArraySlowStubCall(ValueNode hub, ValueNode length) {
-        super(defaultStamp);
-        this.hub = hub;
-        this.length = length;
-    }
-
-    @Override
-    public boolean inferStamp() {
-        if (stamp() == defaultStamp && hub.isConstant()) {
-            updateStamp(StampFactory.exactNonNull(HotSpotResolvedObjectType.fromMetaspaceKlass(hub.asConstant())));
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public void generate(LIRGenerator gen) {
-        RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY_SLOW);
-        Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub), gen.operand(length));
-        gen.setResult(this, result);
-    }
-
-    @NodeIntrinsic
-    public static native Object call(Word hub, int length);
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java	Fri Apr 26 23:03:09 2013 +0200
@@ -97,6 +97,20 @@
         return config().threadTlabStartOffset;
     }
 
+    public static final Object PENDING_EXCEPTION_LOCATION = LocationNode.createLocation("PendingException");
+
+    @Fold
+    private static int threadPendingExceptionOffset() {
+        return config().pendingExceptionOffset;
+    }
+
+    public static final Object OBJECT_RESULT_LOCATION = LocationNode.createLocation("ObjectResult");
+
+    @Fold
+    private static int objectResultOffset() {
+        return config().threadObjectResultOffset;
+    }
+
     public static Object readExceptionOop(Word thread) {
         return thread.readObject(threadExceptionOopOffset(), EXCEPTION_OOP_LOCATION);
     }
@@ -131,6 +145,28 @@
         thread.writeWord(threadTlabEndOffset(), end, TLAB_END_LOCATION);
     }
 
+    /**
+     * Clears the pending exception if for the given thread.
+     * 
+     * @return {@code true} if there was a pending exception
+     */
+    public static boolean clearPendingException(Word thread) {
+        boolean result = thread.readObject(threadPendingExceptionOffset(), PENDING_EXCEPTION_LOCATION) != null;
+        thread.writeObject(threadPendingExceptionOffset(), null);
+        return result;
+    }
+
+    /**
+     * Gets and clears the object result from a runtime call stored in a thread local.
+     * 
+     * @return the object that was in the thread local
+     */
+    public static Object clearObjectResult(Word thread) {
+        Object result = thread.readObject(objectResultOffset(), OBJECT_RESULT_LOCATION);
+        thread.writeObject(objectResultOffset(), null);
+        return result;
+    }
+
     @Fold
     public static int threadObjectOffset() {
         return config().threadObjectOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Apr 26 23:03:09 2013 +0200
@@ -37,6 +37,8 @@
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.word.*;
 
+//JaCoCo Exclude
+
 /**
  * Utilities and common code paths used by the type check snippets.
  */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java	Fri Apr 26 23:03:09 2013 +0200
@@ -22,11 +22,15 @@
  */
 package com.oracle.graal.hotspot.stubs;
 
+import static com.oracle.graal.api.code.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*;
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
@@ -42,7 +46,7 @@
  * Stub implementing the fast path for TLAB refill during instance class allocation. This stub is
  * called from the {@linkplain NewObjectSnippets inline} allocation code when TLAB allocation fails.
  * If this stub fails to refill the TLAB or allocate the object, it calls out to the HotSpot C++
- * runtime for to complete the allocation.
+ * runtime to complete the allocation.
  */
 public class NewArrayStub extends Stub {
 
@@ -54,10 +58,16 @@
     protected Arguments makeArguments(SnippetInfo stub) {
         HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class);
 
+        // RuntimeStub cannot (currently) support oops or metadata embedded in the code so we
+        // convert the hub (i.e., Klass*) for int[] to be a naked word. This should be safe since
+        // the int[] class will never be unloaded.
+        Constant intArrayHub = intArrayType.klass();
+        intArrayHub = Constant.forIntegerKind(graalRuntime().getTarget().wordKind, intArrayHub.asLong(), null);
+
         Arguments args = new Arguments(stub);
         args.add("hub", null);
         args.add("length", null);
-        args.addConst("intArrayHub", intArrayType.klass());
+        args.addConst("intArrayHub", intArrayHub);
         args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub"));
         return args;
     }
@@ -92,7 +102,15 @@
                 return verifyOop(memory.toObject());
             }
         }
-        log(log, "newArray: calling new_array_slow", 0L);
-        return verifyOop(NewArraySlowStubCall.call(hub, length));
+        log(log, "newArray: calling new_array_runtime\n", 0L);
+
+        NewArrayRuntimeCall.call(thread(), hub, length);
+
+        if (clearPendingException(thread())) {
+            log(log, "newArray: deoptimizing to caller\n", 0L);
+            clearObjectResult(thread());
+            DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint);
+        }
+        return verifyOop(clearObjectResult(thread()));
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Fri Apr 26 23:03:09 2013 +0200
@@ -28,6 +28,7 @@
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
@@ -51,6 +52,8 @@
 import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
 import com.oracle.graal.word.*;
 
+//JaCoCo Exclude
+
 /**
  * Base class for implementing some low level code providing the out-of-line slow path for a
  * snippet. A concrete stub is defined a subclass of this class.
@@ -76,13 +79,13 @@
     protected InstalledCode code;
 
     /**
-     * The registers defined by this stub.
+     * The registers/temporaries defined by this stub.
      */
     private Set<Register> definedRegisters;
 
     public void initDefinedRegisters(Set<Register> registers) {
         assert registers != null;
-        assert definedRegisters == null : "cannot redefine";
+        assert definedRegisters == null || registers.equals(definedRegisters) : "cannot redefine";
         definedRegisters = registers;
     }
 
@@ -123,6 +126,17 @@
         return linkage;
     }
 
+    private boolean checkCompilationResult(CompilationResult compResult) {
+        if (this instanceof NewArrayStub) {
+            for (DataPatch data : compResult.getDataReferences()) {
+                Constant constant = data.constant;
+                assert constant.getKind() != Kind.Object : MetaUtil.format("%h.%n(%p): ", getMethod()) + "cannot have embedded oop: " + constant;
+                assert constant.getPrimitiveAnnotation() == null : MetaUtil.format("%h.%n(%p): ", getMethod()) + "cannot have embedded metadata: " + constant;
+            }
+        }
+        return true;
+    }
+
     /**
      * Gets the code for this stub, compiling it first if necessary.
      */
@@ -143,6 +157,8 @@
                     final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan,
                                     OptimisticOptimizations.ALL, new SpeculationLog());
 
+                    assert checkCompilationResult(compResult);
+
                     assert definedRegisters != null;
                     code = Debug.scope("CodeInstall", new Callable<InstalledCode>() {
 
@@ -156,7 +172,6 @@
                             return installedCode;
                         }
                     });
-
                 }
             });
             assert code != null : "error installing stub " + getMethod();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegisterPreservationOp.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 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.lir.amd64;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Base class for the operations that save or restore registers around another operation that may
+ * potentially destroy any register (e.g., a call).
+ */
+public abstract class AMD64RegisterPreservationOp extends AMD64LIRInstruction {
+
+    protected static void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value[] dst, Value[] src) {
+        for (int i = 0; i < dst.length; i++) {
+            if (dst[i] != null) {
+                AMD64Move.move(tasm, masm, dst[i], src[i]);
+            } else {
+                assert src[i] == null;
+            }
+        }
+    }
+
+    protected static void doNotPreserve(Set<Register> registers, RegisterValue[] registerValues, StackSlot[] slots) {
+        for (int i = 0; i < slots.length; i++) {
+            if (registerValues[i] != null) {
+                if (registers.contains(registerValues[i].getRegister())) {
+                    registerValues[i] = null;
+                    slots[i] = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * Records that no registers in {@code registers} need to be preserved.
+     */
+    public abstract void doNotPreserve(Set<Register> registers);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 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.lir.amd64;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Restores registers from stack slots.
+ */
+@Opcode("RESTORE_REGISTER")
+public final class AMD64RestoreRegistersOp extends AMD64RegisterPreservationOp {
+
+    @Use(STACK) protected StackSlot[] src;
+    @Def(REG) protected RegisterValue[] dst;
+
+    public AMD64RestoreRegistersOp(StackSlot[] src, RegisterValue[] dst) {
+        this.src = src;
+        this.dst = dst;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        emitCode(tasm, masm, dst, src);
+    }
+
+    @Override
+    public void doNotPreserve(Set<Register> registers) {
+        doNotPreserve(registers, dst, src);
+    }
+
+    /**
+     * Updates {@code debugInfo} with a description of where each preserved register is saved.
+     */
+    public void describePreservation(DebugInfo debugInfo, FrameMap frameMap) {
+        int preserved = 0;
+        for (RegisterValue r : dst) {
+            if (r != null) {
+                preserved++;
+            }
+        }
+        if (preserved != 0) {
+            Register[] keys = new Register[preserved];
+            int[] values = new int[keys.length];
+            int mapIndex = 0;
+            for (int i = 0; i < src.length; i++) {
+                if (dst[i] != null) {
+                    keys[mapIndex] = dst[i].getRegister();
+                    values[mapIndex] = frameMap.indexForStackSlot(src[i]);
+                    mapIndex++;
+                }
+            }
+            assert mapIndex == preserved;
+            debugInfo.setCalleeSaveInfo(new RegisterSaveLayout(keys, values));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Fri Apr 26 23:03:09 2013 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 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.lir.amd64;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Saves registers to stack slots.
+ */
+@Opcode("SAVE_REGISTER")
+public final class AMD64SaveRegistersOp extends AMD64RegisterPreservationOp {
+
+    @Use(REG) protected RegisterValue[] src;
+    @Def(STACK) protected StackSlot[] dst;
+
+    public AMD64SaveRegistersOp(RegisterValue[] src, StackSlot[] dst) {
+        this.src = src;
+        this.dst = dst;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        emitCode(tasm, masm, dst, src);
+    }
+
+    @Override
+    public void doNotPreserve(Set<Register> registers) {
+        doNotPreserve(registers, src, dst);
+    }
+
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Fri Apr 26 23:03:09 2013 +0200
@@ -210,8 +210,7 @@
     }
 
     /**
-     * Computes the offset of a stack slot relative to the frame register. This is also the bit
-     * index of stack slots in the reference map.
+     * Computes the offset of a stack slot relative to the frame register.
      * 
      * @param slot a stack slot
      * @return the offset of the stack slot
@@ -226,6 +225,18 @@
     }
 
     /**
+     * Computes the index of a stack slot relative to slot 0. This is also the bit index of stack
+     * slots in the reference map.
+     * 
+     * @param slot a stack slot
+     * @return the index of the stack slot
+     */
+    public int indexForStackSlot(StackSlot slot) {
+        assert offsetForStackSlot(slot) % target.wordSize == 0;
+        return offsetForStackSlot(slot) / target.wordSize;
+    }
+
+    /**
      * Gets the offset to the stack area where callee-saved registers are stored.
      * 
      * @return The offset to the callee save area (in bytes).
@@ -285,7 +296,7 @@
         return getSlot(kind, 0);
     }
 
-    private List<StackSlot> freedSlots;
+    private Set<StackSlot> freedSlots;
 
     /**
      * Frees a spill slot that was obtained via {@link #allocateSpillSlot(Kind)} such that it can be
@@ -293,7 +304,7 @@
      */
     public void freeSpillSlot(StackSlot slot) {
         if (freedSlots == null) {
-            freedSlots = new ArrayList<>();
+            freedSlots = new HashSet<>();
         }
         freedSlots.add(slot);
     }
@@ -329,11 +340,6 @@
         }
     }
 
-    private int frameRefMapIndex(StackSlot slot) {
-        assert offsetForStackSlot(slot) % target.wordSize == 0;
-        return offsetForStackSlot(slot) / target.wordSize;
-    }
-
     /**
      * Initializes a reference map that covers all registers of the target architecture.
      */
@@ -368,7 +374,7 @@
             if (isRegister(location)) {
                 registerRefMap.set(asRegister(location).number);
             } else if (isStackSlot(location)) {
-                int index = frameRefMapIndex(asStackSlot(location));
+                int index = indexForStackSlot(asStackSlot(location));
                 frameRefMap.set(index);
             } else {
                 assert isConstant(location);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Fri Apr 26 23:03:09 2013 +0200
@@ -113,7 +113,7 @@
 
             Debug.metric("TargetMethods").increment();
             Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize());
-            Debug.metric("SafepointsEmitted").add(compilationResult.getInfopoints().size());
+            Debug.metric("InfopointsEmitted").add(compilationResult.getInfopoints().size());
             Debug.metric("DataPatches").add(ldp.size());
             Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size());
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Fri Apr 26 23:03:09 2013 +0200
@@ -144,7 +144,7 @@
         }
         if (node instanceof FixedWithNextNode) {
             ((StructuredGraph) graph()).replaceFixedWithFixed(this, (FixedWithNextNode) node);
-        } else if (node instanceof DeoptimizeNode) {
+        } else if (node instanceof ControlSinkNode) {
             this.replaceAtPredecessor(node);
             this.replaceAtUsages(null);
             GraphUtil.killCFG(this);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Fri Apr 26 23:03:09 2013 +0200
@@ -188,7 +188,7 @@
         if (node == null) {
             assert kind() == Kind.Void && usages().isEmpty();
             ((StructuredGraph) graph()).removeSplit(this, next());
-        } else if (node instanceof DeoptimizeNode) {
+        } else if (node instanceof ControlSinkNode) {
             this.replaceAtPredecessor(node);
             this.replaceAtUsages(null);
             GraphUtil.killCFG(this);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Fri Apr 26 23:03:09 2013 +0200
@@ -446,9 +446,10 @@
                 @Override
                 protected void doState(LIRFrameState state) {
                     if (state.hasDebugInfo()) {
-                        stateString.append(debugInfoToString(state.debugInfo().getBytecodePosition(), state.debugInfo().getRegisterRefMap(), state.debugInfo().getFrameRefMap(), target.arch));
+                        DebugInfo di = state.debugInfo();
+                        stateString.append(debugInfoToString(di.getBytecodePosition(), di.getRegisterRefMap(), di.getFrameRefMap(), di.getCalleeSaveInfo(), target.arch));
                     } else {
-                        stateString.append(debugInfoToString(state.topFrame, null, null, target.arch));
+                        stateString.append(debugInfoToString(state.topFrame, null, null, null, target.arch));
                     }
                 }
             });
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Fri Apr 26 23:03:09 2013 +0200
@@ -114,7 +114,7 @@
     /**
      * Formats given debug info as a multi line string.
      */
-    protected String debugInfoToString(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, Architecture arch) {
+    protected String debugInfoToString(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, RegisterSaveLayout calleeSaveInfo, Architecture arch) {
         StringBuilder sb = new StringBuilder();
 
         if (registerRefMap != null) {
@@ -128,8 +128,16 @@
 
         if (frameRefMap != null) {
             sb.append("frame-ref-map:");
-            for (int reg = frameRefMap.nextSetBit(0); reg >= 0; reg = frameRefMap.nextSetBit(reg + 1)) {
-                sb.append(' ').append("s").append(reg);
+            for (int slot = frameRefMap.nextSetBit(0); slot >= 0; slot = frameRefMap.nextSetBit(slot + 1)) {
+                sb.append(' ').append("s").append(slot);
+            }
+            sb.append("\n");
+        }
+
+        if (calleeSaveInfo != null) {
+            sb.append("callee-save-info:");
+            for (Map.Entry<Register, Integer> e : calleeSaveInfo.registersToSlots(true).entrySet()) {
+                sb.append(" " + e.getKey() + " -> s" + e.getValue());
             }
             sb.append("\n");
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Apr 26 22:44:05 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Apr 26 23:03:09 2013 +0200
@@ -296,7 +296,14 @@
         private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy) {
             StructuredGraph graph = graphCache.get(methodToParse);
             if (graph == null) {
-                graphCache.putIfAbsent(methodToParse, buildGraph(methodToParse, policy == null ? inliningPolicy(methodToParse) : policy));
+                StructuredGraph newGraph = Debug.scope("ParseGraph", new Object[]{methodToParse}, new Callable<StructuredGraph>() {
+
+                    public StructuredGraph call() throws Exception {
+                        return buildGraph(methodToParse, policy == null ? inliningPolicy(methodToParse) : policy);
+                    }
+                });
+
+                graphCache.putIfAbsent(methodToParse, newGraph);
                 graph = graphCache.get(methodToParse);
                 assert graph != null;
             }
@@ -312,8 +319,6 @@
             GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE);
             graphBuilder.apply(graph);
 
-            Debug.dump(graph, "%s: %s", methodToParse.getName(), GraphBuilderPhase.class.getSimpleName());
-
             new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
 
             return graph;
@@ -367,6 +372,11 @@
                         if (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)) {
                             targetGraph = intrinsicGraph;
                         } else {
+                            if (callee.getName().startsWith("$jacoco")) {
+                                throw new GraalInternalError("Parsing call to JaCoCo instrumentation method " + format("%H.%n(%p)", callee) + " from " + format("%H.%n(%p)", methodToParse) +
+                                                " while preparing replacement " + format("%H.%n(%p)", method) + ". Placing \"//JaCoCo Exclude\" anywhere in " +
+                                                methodToParse.getDeclaringClass().getSourceFileName() + " should fix this.");
+                            }
                             targetGraph = parseGraph(callee, policy);
                         }
                         InliningUtil.inline(callTarget.invoke(), targetGraph, true);
--- a/mx/commands.py	Fri Apr 26 22:44:05 2013 +0200
+++ b/mx/commands.py	Fri Apr 26 23:03:09 2013 +0200
@@ -749,7 +749,7 @@
             excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution', '@Test'], includeInnerClasses=True).keys()
             excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys()
             
-        includes = ['com.oracle.graal.*', 'com.oracle.max.*']
+        includes = ['com.oracle.graal.*']
         agentOptions = {
                         'append' : 'true' if _jacoco == 'append' else 'false',
                         'bootclasspath' : 'true',
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Apr 26 23:03:09 2013 +0200
@@ -183,7 +183,7 @@
   do_klass(Long_klass,                                  java_lang_Long,                            Pre                 ) \
                                                                                                                          \
   /* Support for Graal */                                                                                                \
-  do_klass(GraalBitMap_klass,                     java_util_BitSet,                                             Opt) \
+  do_klass(BitSet_klass,                          java_util_BitSet,                                             Opt) \
   /* graal.hotspot */                                                                                                \
   do_klass(HotSpotCompilationResult_klass,        com_oracle_graal_hotspot_HotSpotCompilationResult,            Opt) \
   do_klass(HotSpotRuntimeCallTarget_klass,        com_oracle_graal_hotspot_HotSpotRuntimeCallTarget,            Opt) \
@@ -205,6 +205,7 @@
   do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue,    Opt) \
   do_klass(BytecodePosition_klass,                com_oracle_graal_api_code_BytecodePosition,                   Opt) \
   do_klass(DebugInfo_klass,                       com_oracle_graal_api_code_DebugInfo,                          Opt) \
+  do_klass(RegisterSaveLayout_klass,              com_oracle_graal_api_code_RegisterSaveLayout,                 Opt) \
   do_klass(BytecodeFrame_klass,                   com_oracle_graal_api_code_BytecodeFrame,                      Opt) \
   do_klass(CompilationResult_klass,               com_oracle_graal_api_code_CompilationResult,                  Opt) \
   do_klass(CompilationResult_Call_klass,          com_oracle_graal_api_code_CompilationResult_Call,             Opt) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 26 23:03:09 2013 +0200
@@ -341,6 +341,7 @@
   template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue")                       \
   template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot")                           \
   template(com_oracle_graal_api_code_VirtualObject,                  "com/oracle/graal/api/code/VirtualObject")                       \
+  template(com_oracle_graal_api_code_RegisterSaveLayout,             "com/oracle/graal/api/code/RegisterSaveLayout")                  \
   template(com_oracle_graal_api_code_InvalidInstalledCodeException,  "com/oracle/graal/api/code/InvalidInstalledCodeException")       \
   template(startCompiler_name,                    "startCompiler")                                                                    \
   template(bootstrap_name,                        "bootstrap")                                                                        \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Fri Apr 26 23:03:09 2013 +0200
@@ -68,41 +68,48 @@
 
 const int MapWordBits = 64;
 
-static bool is_bit_set(oop bit_map, int i) {
-  jint extra_idx = i / MapWordBits;
-  arrayOop extra = (arrayOop) GraalBitMap::words(bit_map);
-  assert(extra_idx >= 0 && extra_idx < extra->length(), "unexpected index");
-  jlong word = ((jlong*) extra->base(T_LONG))[extra_idx];
+static bool is_bit_set(oop bitset, int i) {
+  jint words_idx = i / MapWordBits;
+  arrayOop words = (arrayOop) BitSet::words(bitset);
+  assert(words_idx >= 0 && words_idx < words->length(), "unexpected index");
+  jlong word = ((jlong*) words->base(T_LONG))[words_idx];
   return (word & (1LL << (i % MapWordBits))) != 0;
 }
 
-static int bitmap_size(oop bit_map) {
-  arrayOop arr = (arrayOop) GraalBitMap::words(bit_map);
+static int bitset_size(oop bitset) {
+  arrayOop arr = (arrayOop) BitSet::words(bitset);
   return arr->length() * MapWordBits;
 }
 
+#ifdef _LP64
+  #define SLOTS_PER_WORD 2
+#else
+  #define SLOTS_PER_WORD 1
+#endif // _LP64
+
 // creates a HotSpot oop map out of the byte arrays provided by DebugInfo
 static OopMap* create_oop_map(jint total_frame_size, jint parameter_count, oop debug_info) {
   OopMap* map = new OopMap(total_frame_size, parameter_count);
   oop register_map = (oop) DebugInfo::registerRefMap(debug_info);
   oop frame_map = (oop) DebugInfo::frameRefMap(debug_info);
+  oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info);
 
   if (register_map != NULL) {
     for (jint i = 0; i < RegisterImpl::number_of_registers; i++) {
       bool is_oop = is_bit_set(register_map, i);
-      VMReg reg = get_hotspot_reg(i);
+      VMReg hotspot_reg = get_hotspot_reg(i);
       if (is_oop) {
-        map->set_oop(reg);
+        map->set_oop(hotspot_reg);
       } else {
-        map->set_value(reg);
+        map->set_value(hotspot_reg);
       }
     }
   }
 
-  for (jint i = 0; i < bitmap_size(frame_map); i++) {
+  for (jint i = 0; i < bitset_size(frame_map); i++) {
     bool is_oop = is_bit_set(frame_map, i);
     // HotSpot stack slots are 4 bytes
-    VMReg reg = VMRegImpl::stack2reg(i * 2);
+    VMReg reg = VMRegImpl::stack2reg(i * SLOTS_PER_WORD);
     if (is_oop) {
       map->set_oop(reg);
     } else {
@@ -110,6 +117,26 @@
     }
   }
 
+  if (callee_save_info != NULL) {
+    objArrayOop registers = (objArrayOop) RegisterSaveLayout::registers(callee_save_info);
+    arrayOop slots = (arrayOop) RegisterSaveLayout::slots(callee_save_info);
+    for (jint i = 0; i < slots->length(); i++) {
+      oop graal_reg = registers->obj_at(i);
+      jint graal_reg_number = code_Register::number(graal_reg);
+      VMReg hotspot_reg = get_hotspot_reg(graal_reg_number);
+      // HotSpot stack slots are 4 bytes
+      jint graal_slot = ((jint*) slots->base(T_INT))[i];
+      jint hotspot_slot = graal_slot * SLOTS_PER_WORD;
+      VMReg hotspot_slot_as_reg = VMRegImpl::stack2reg(hotspot_slot);
+      map->set_callee_saved(hotspot_slot_as_reg, hotspot_reg);
+#ifdef _LP64
+      // (copied from generate_oop_map() in c1_Runtime1_x86.cpp)
+      VMReg hotspot_slot_hi_as_reg = VMRegImpl::stack2reg(hotspot_slot + 1);
+      map->set_callee_saved(hotspot_slot_hi_as_reg, hotspot_reg->next());
+#endif
+    }
+  }
+
   return map;
 }
 
@@ -330,7 +357,7 @@
 }
 
 // constructor used to create a method
-CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code, Handle triggered_deoptimizations) {
+CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations) {
   GraalCompiler::initialize_buffer_blob();
   CodeBuffer buffer(JavaThread::current()->get_buffer_blob());
   jobject comp_result_obj = JNIHandles::make_local(comp_result());
@@ -347,8 +374,21 @@
   int stack_slots = _total_frame_size / HeapWordSize; // conversion to words
   GrowableArray<jlong>* leaf_graph_ids = get_leaf_graph_ids(comp_result);
 
-  result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
-    GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, false, leaf_graph_ids, installed_code, triggered_deoptimizations);
+  if (_stubName != NULL) {
+    char* name = strdup(java_lang_String::as_utf8_string(_stubName));
+    cb = RuntimeStub::new_runtime_stub(name,
+                                       &buffer,
+                                       CodeOffsets::frame_never_safe,
+                                       stack_slots,
+                                       _debug_recorder->_oopmaps,
+                                       false);
+    result = GraalEnv::ok;
+  } else {
+    nmethod* nm = NULL;
+    result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+        GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, false, leaf_graph_ids, installed_code, triggered_deoptimizations);
+    cb = nm;
+  }
 }
 
 void CodeInstaller::initialize_fields(oop comp_result, methodHandle method) {
@@ -357,7 +397,7 @@
     _parameter_count = method->size_of_parameters();
     TRACE_graal_1("installing code for %s", method->name_and_sig_as_C_string());
   }
-  _name = HotSpotCompilationResult::name(comp_result);
+  _stubName = HotSpotCompilationResult::stubName(comp_result);
   _sites = (arrayOop) HotSpotCompilationResult::sites(comp_result);
   _exception_handlers = (arrayOop) HotSpotCompilationResult::exceptionHandlers(comp_result);
 
@@ -640,8 +680,14 @@
   if (target->is_a(SystemDictionary::HotSpotInstalledCode_klass())) {
     assert(inst->is_jump(), "jump expected");
 
-    nmethod* nm = (nmethod*) HotSpotInstalledCode::nmethod(target);
-    nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
+    CodeBlob* cb = (CodeBlob*) (address) HotSpotInstalledCode::codeBlob(target);
+    assert(cb != NULL, "npe");
+    if (cb->is_nmethod()) {
+      nmethod* nm = (nmethod*) cb;
+      nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
+    } else {
+      nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
+    }
     _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
 
     return;
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Fri Apr 26 23:03:09 2013 +0200
@@ -51,7 +51,7 @@
   Arena         _arena;
 
   oop           _comp_result;
-  oop           _name;
+  oop           _stubName;
   arrayOop      _sites;
   arrayOop      _exception_handlers;
   CodeOffsets   _offsets;
@@ -76,11 +76,7 @@
 
 public:
 
-  // constructor used to create a method
-  CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code, Handle triggered_deoptimizations);
-
-  // constructor used to create a stub
-  CodeInstaller(Handle& target_method, BufferBlob*& blob, jlong& id);
+  CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations);
 
   static address runtime_call_target_address(oop runtime_call);
 
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Fri Apr 26 23:03:09 2013 +0200
@@ -620,7 +620,7 @@
 #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0)
 #define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0)
 #define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0)
-#define set_stub(name, value) do { set_long(name, (jlong) value); } while (0)
+#define set_address(name, value) do { set_long(name, (jlong) value); } while (0)
 #define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0)
 #define set_int_array(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "[I"), value); } while (0)
 
@@ -699,6 +699,7 @@
   set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset()));
 
 
+  set_int("pendingExceptionOffset", in_bytes(ThreadShadow::pending_exception_offset()));
   set_int("pendingDeoptimizationOffset", in_bytes(ThreadShadow::pending_deoptimization_offset()));
 
   set_int("metaspaceArrayLengthOffset", Array<Klass*>::length_offset_in_bytes());
@@ -721,6 +722,10 @@
   set_int("threadTlabStartOffset", in_bytes(JavaThread::tlab_start_offset()));
   set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset()));
   set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset()));
+  set_int("threadLastJavaSpOffset", in_bytes(JavaThread::last_Java_sp_offset()));
+  set_int("threadLastJavaFpOffset", in_bytes(JavaThread::last_Java_fp_offset()));
+  set_int("threadLastJavaPcOffset", in_bytes(JavaThread::last_Java_pc_offset()));
+  set_int("threadObjectResultOffset", in_bytes(JavaThread::vm_result_offset()));
   set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset()));
   set_int("tlabFastRefillWasteOffset", in_bytes(JavaThread::tlab_fast_refill_waste_offset()));
   set_int("tlabNumberOfRefillsOffset", in_bytes(JavaThread::tlab_number_of_refills_offset()));
@@ -742,42 +747,44 @@
   set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset()));
 
 
-  set_stub("wbPreCallStub", GraalRuntime::entry_for(GraalRuntime::wb_pre_call_id));
-  set_stub("wbPostCallStub", GraalRuntime::entry_for(GraalRuntime::wb_post_call_id));
+  set_address("wbPreCallStub", GraalRuntime::entry_for(GraalRuntime::wb_pre_call_id));
+  set_address("wbPostCallStub", GraalRuntime::entry_for(GraalRuntime::wb_post_call_id));
 
-  set_stub("newInstanceStub", GraalRuntime::entry_for(GraalRuntime::new_instance_id));
-  set_stub("newArrayStub", GraalRuntime::entry_for(GraalRuntime::new_array_id));
-  set_stub("newMultiArrayStub", GraalRuntime::entry_for(GraalRuntime::new_multi_array_id));
-  set_stub("identityHashCodeStub", GraalRuntime::entry_for(GraalRuntime::identity_hash_code_id));
-  set_stub("threadIsInterruptedStub", GraalRuntime::entry_for(GraalRuntime::thread_is_interrupted_id));
-  set_stub("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub());
-  set_stub("handleExceptionStub", GraalRuntime::entry_for(GraalRuntime::handle_exception_nofpu_id));
-  set_stub("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
-  set_stub("monitorEnterStub", GraalRuntime::entry_for(GraalRuntime::monitorenter_id));
-  set_stub("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::monitorexit_id));
-  set_stub("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::verify_oop_id));
-  set_stub("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::vm_error_id));
-  set_stub("deoptimizeStub", SharedRuntime::deopt_blob()->uncommon_trap());
-  set_stub("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::unwind_exception_call_id));
-  set_stub("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::OSR_migration_end_id));
-  set_stub("registerFinalizerStub", GraalRuntime::entry_for(GraalRuntime::register_finalizer_id));
-  set_stub("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_null_pointer_exception_id));
-  set_stub("createOutOfBoundsExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_out_of_bounds_exception_id));
-  set_stub("javaTimeMillisStub", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
-  set_stub("javaTimeNanosStub", CAST_FROM_FN_PTR(address, os::javaTimeNanos));
-  set_stub("arithmeticFremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_frem_id));
-  set_stub("arithmeticDremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_drem_id));
-  set_stub("arithmeticSinStub", CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
-  set_stub("arithmeticCosStub", CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
-  set_stub("arithmeticTanStub", CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
-  set_stub("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id));
-  set_stub("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id));
-  set_stub("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id));
-  set_stub("stubPrintfStub", GraalRuntime::entry_for(GraalRuntime::stub_printf_id));
-  set_stub("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock());
-  set_stub("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock());
-  set_stub("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt());
-  set_stub("cipherBlockChainingDecryptAESCryptStub", StubRoutines::cipherBlockChaining_decryptAESCrypt());
+  set_address("newInstanceStub", GraalRuntime::entry_for(GraalRuntime::new_instance_id));
+  set_address("newArrayStub", GraalRuntime::entry_for(GraalRuntime::new_array_id));
+  set_address("newMultiArrayStub", GraalRuntime::entry_for(GraalRuntime::new_multi_array_id));
+  set_address("identityHashCodeStub", GraalRuntime::entry_for(GraalRuntime::identity_hash_code_id));
+  set_address("threadIsInterruptedStub", GraalRuntime::entry_for(GraalRuntime::thread_is_interrupted_id));
+  set_address("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub());
+  set_address("handleExceptionStub", GraalRuntime::entry_for(GraalRuntime::handle_exception_nofpu_id));
+  set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack());
+  set_address("monitorEnterStub", GraalRuntime::entry_for(GraalRuntime::monitorenter_id));
+  set_address("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::monitorexit_id));
+  set_address("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::verify_oop_id));
+  set_address("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::vm_error_id));
+  set_address("deoptimizeStub", SharedRuntime::deopt_blob()->uncommon_trap());
+  set_address("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::unwind_exception_call_id));
+  set_address("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::OSR_migration_end_id));
+  set_address("registerFinalizerStub", GraalRuntime::entry_for(GraalRuntime::register_finalizer_id));
+  set_address("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_null_pointer_exception_id));
+  set_address("createOutOfBoundsExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_out_of_bounds_exception_id));
+  set_address("javaTimeMillisStub", CAST_FROM_FN_PTR(address, os::javaTimeMillis));
+  set_address("javaTimeNanosStub", CAST_FROM_FN_PTR(address, os::javaTimeNanos));
+  set_address("arithmeticFremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_frem_id));
+  set_address("arithmeticDremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_drem_id));
+  set_address("arithmeticSinStub", CAST_FROM_FN_PTR(address, SharedRuntime::dsin));
+  set_address("arithmeticCosStub", CAST_FROM_FN_PTR(address, SharedRuntime::dcos));
+  set_address("arithmeticTanStub", CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
+  set_address("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id));
+  set_address("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id));
+  set_address("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id));
+  set_address("stubPrintfStub", GraalRuntime::entry_for(GraalRuntime::stub_printf_id));
+  set_address("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock());
+  set_address("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock());
+  set_address("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt());
+  set_address("cipherBlockChainingDecryptAESCryptStub", StubRoutines::cipherBlockChaining_decryptAESCrypt());
+
+  set_address("newArrayAddress", GraalRuntime::new_array);
 
   set_int("deoptReasonNone", Deoptimization::Reason_none);
   set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check);
@@ -849,12 +856,13 @@
   ResourceMark rm;
   HandleMark hm;
   Handle compResultHandle = JNIHandles::resolve(compResult);
-  nmethod* nm = NULL;
+  CodeBlob* cb = NULL;
   methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(compResult));
   Handle installed_code_handle = JNIHandles::resolve(installed_code);
   Handle triggered_deoptimizations_handle = JNIHandles::resolve(triggered_deoptimizations);
   GraalEnv::CodeInstallResult result;
-  CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle, triggered_deoptimizations_handle);
+
+  CodeInstaller installer(compResultHandle, method, result, cb, installed_code_handle, triggered_deoptimizations_handle);
 
   if (PrintCodeCacheOnCompilation) {
     stringStream s;
@@ -868,13 +876,15 @@
   }
 
   if (result != GraalEnv::ok) {
-    assert(nm == NULL, "should be");
+    assert(cb == NULL, "should be");
   } else {
     if (!installed_code_handle.is_null()) {
       assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type");
-      HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm);
+      HotSpotInstalledCode::set_codeBlob(installed_code_handle, (jlong) cb);
       HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult));
-      HotSpotInstalledCode::set_start(installed_code_handle, (jlong) nm->code_begin());
+      HotSpotInstalledCode::set_start(installed_code_handle, (jlong) cb->code_begin());
+      HotSpotInstalledCode::set_isNmethod(installed_code_handle, cb->is_nmethod());
+      nmethod* nm = cb->as_nmethod_or_null();
       assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable");
     }
   }
@@ -886,30 +896,53 @@
   method->clear_queued_for_compilation();
 C2V_END
 
-C2V_VMENTRY(jobject, getCode, (JNIEnv *jniEnv, jobject,  jlong metaspace_nmethod))
+C2V_VMENTRY(jobject, getCode, (JNIEnv *jniEnv, jobject,  jlong codeBlob))
+  ResourceMark rm;
+  HandleMark hm;
+
+  CodeBlob* cb = (CodeBlob*) (address) codeBlob;
+  if (cb == NULL) {
+    return NULL;
+  }
+  if (cb->is_nmethod()) {
+    nmethod* nm = (nmethod*) cb;
+    if (!nm->is_alive()) {
+      return NULL;
+    }
+  }
+  int length = cb->code_size();
+  arrayOop codeCopy = oopFactory::new_byteArray(length, CHECK_0);
+  memcpy(codeCopy->base(T_BYTE), cb->code_begin(), length);
+  return JNIHandles::make_local(codeCopy);
+C2V_END
+
+C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob))
   ResourceMark rm;
   HandleMark hm;
 
-  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
-  if (nm == NULL || !nm->is_alive()) {
+  CodeBlob* cb = (CodeBlob*) (address) codeBlob;
+  if (cb == NULL) {
     return NULL;
   }
-  int length = nm->code_size();
-  arrayOop codeCopy = oopFactory::new_byteArray(length, CHECK_0);
-  memcpy(codeCopy->base(T_BYTE), nm->code_begin(), length);
-  return JNIHandles::make_local(codeCopy);
-C2V_END
 
-C2V_VMENTRY(jobject, disassembleNMethod, (JNIEnv *jniEnv, jobject, jlong metaspace_nmethod))
-  ResourceMark rm;
-  HandleMark hm;
-
-  nmethod* nm = (nmethod*) (address) metaspace_nmethod;
-  if (nm == NULL || !nm->is_alive()) {
-    return NULL;
+  // We don't want the stringStream buffer to resize during disassembly as it
+  // uses scoped resource memory. If a nested function called during disassembly uses
+  // a ResourceMark and the buffer expands within the scope of the mark,
+  // the buffer becomes garbage when that scope is exited. Experience shows that
+  // the disassembled code is typically about 10x the code size so a fixed buffer
+  // sized to 20x code size should be sufficient.
+  int bufferSize = cb->code_size() * 20;
+  char* buffer = NEW_RESOURCE_ARRAY(char, bufferSize);
+  stringStream st(buffer, bufferSize);
+  if (cb->is_nmethod()) {
+    nmethod* nm = (nmethod*) cb;
+    if (!nm->is_alive()) {
+      return NULL;
+    }
+    Disassembler::decode(nm, &st);
+  } else {
+    Disassembler::decode(cb, &st);
   }
-  stringStream(st);
-  Disassembler::decode(nm, &st);
 
   Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL);
   return JNIHandles::make_local(result());
@@ -924,11 +957,11 @@
   return JNIHandles::make_local(element);
 C2V_END
 
-C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nativeMethod))
+C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nmethodValue))
   ResourceMark rm;
   HandleMark hm;
 
-  nmethod* nm = (nmethod*) (address) nativeMethod;
+  nmethod* nm = (nmethod*) (address) nmethodValue;
   methodHandle mh = nm->method();
   Symbol* signature = mh->signature();
   JavaCallArguments jca(mh->size_of_parameters());
@@ -1150,7 +1183,7 @@
   {CC"initializeConfiguration",       CC"("HS_CONFIG")V",                                               FN_PTR(initializeConfiguration)},
   {CC"installCode0",                  CC"("HS_COMP_RESULT HS_INSTALLED_CODE"[Z)I",                      FN_PTR(installCode0)},
   {CC"getCode",                       CC"(J)[B",                                                        FN_PTR(getCode)},
-  {CC"disassembleNMethod",            CC"(J)"STRING,                                                    FN_PTR(disassembleNMethod)},
+  {CC"disassembleCodeBlob",           CC"(J)"STRING,                                                    FN_PTR(disassembleCodeBlob)},
   {CC"executeCompiledMethodVarargs",  CC"(["OBJECT NMETHOD")"OBJECT,                                    FN_PTR(executeCompiledMethodVarargs)},
   {CC"getDeoptedLeafGraphIds",        CC"()[J",                                                         FN_PTR(getDeoptedLeafGraphIds)},
   {CC"getLineNumberTable",            CC"("HS_RESOLVED_METHOD")[J",                                     FN_PTR(getLineNumberTable)},
--- a/src/share/vm/graal/graalJavaAccess.cpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.cpp	Fri Apr 26 23:03:09 2013 +0200
@@ -32,7 +32,7 @@
   Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name));
   Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature));
 #ifndef PRODUCT
-  if (name_symbol == NULL) {
+  if (name_symbol == NULL || signature_symbol == NULL) {
     tty->print_cr("symbol with name %s was not found in symbol table (klass=%s)", name, klass->name()->as_C_string());
   }
 #endif
--- a/src/share/vm/graal/graalJavaAccess.hpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Fri Apr 26 23:03:09 2013 +0200
@@ -73,15 +73,16 @@
     int_field(HotSpotResolvedJavaField, flags)                                                                                                                 \
   end_class                                                                                                                                                    \
   start_class(HotSpotInstalledCode)                                                                                                                            \
-    long_field(HotSpotInstalledCode, nmethod)                                                                                                                  \
+    long_field(HotSpotInstalledCode, codeBlob)                                                                                                                 \
     oop_field(HotSpotInstalledCode, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;")                                                       \
     long_field(HotSpotInstalledCode, start)                                                                                                                    \
     boolean_field(HotSpotInstalledCode, isDefault)                                                                                                             \
+    boolean_field(HotSpotInstalledCode, isNmethod)                                                                                                             \
   end_class                                                                                                                                                    \
   start_class(HotSpotCompilationResult)                                                                                                                        \
     oop_field(HotSpotCompilationResult, comp, "Lcom/oracle/graal/api/code/CompilationResult;")                                                                 \
     oop_field(HotSpotCompilationResult, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;")                                                   \
-    oop_field(HotSpotCompilationResult, name, "Ljava/lang/String;")                                                                                            \
+    oop_field(HotSpotCompilationResult, stubName, "Ljava/lang/String;")                                                                                        \
     int_field(HotSpotCompilationResult, entryBCI)                                                                                                              \
     oop_field(HotSpotCompilationResult, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;")                                                          \
     oop_field(HotSpotCompilationResult, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;")                                  \
@@ -162,9 +163,14 @@
     oop_field(DebugInfo, bytecodePosition, "Lcom/oracle/graal/api/code/BytecodePosition;")                                                                     \
     oop_field(DebugInfo, registerRefMap, "Ljava/util/BitSet;")                                                                                                 \
     oop_field(DebugInfo, frameRefMap, "Ljava/util/BitSet;")                                                                                                    \
+    oop_field(DebugInfo, calleeSaveInfo, "Lcom/oracle/graal/api/code/RegisterSaveLayout;")                                                                     \
   end_class                                                                                                                                                    \
-  start_class(GraalBitMap)                                                                                                                                     \
-    oop_field(GraalBitMap, words, "[J")                                                                                                                        \
+  start_class(RegisterSaveLayout)                                                                                                                              \
+    oop_field(RegisterSaveLayout, registers, "[Lcom/oracle/graal/api/code/Register;")                                                                          \
+    oop_field(RegisterSaveLayout, slots, "[I")                                                                                                                 \
+  end_class                                                                                                                                                    \
+  start_class(BitSet)                                                                                                                                          \
+    oop_field(BitSet, words, "[J")                                                                                                                             \
   end_class                                                                                                                                                    \
   start_class(BytecodeFrame)                                                                                                                                   \
     oop_field(BytecodeFrame, values, "[Lcom/oracle/graal/api/meta/Value;")                                                                                     \
--- a/src/share/vm/graal/graalRuntime.cpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Fri Apr 26 23:03:09 2013 +0200
@@ -260,11 +260,16 @@
   // This is pretty rare but this runtime patch is stressful to deoptimization
   // if we deoptimize here so force a deopt to stress the path.
   if (DeoptimizeALot) {
-    deopt_caller();
+    static int deopts = 0;
+    // Alternate between deoptimizing and raising an error (which will also cause a deopt)
+    if (deopts++ % 2 == 0) {
+      ResourceMark rm(THREAD);
+      THROW(vmSymbols::java_lang_OutOfMemoryError());
+    } else {
+      deopt_caller();
+    }
   }
- JRT_END
-
-
+JRT_END
 
 JRT_ENTRY(void, GraalRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims))
   assert(klass->is_klass(), "not a class");
--- a/src/share/vm/graal/graalRuntime.hpp	Fri Apr 26 22:44:05 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Fri Apr 26 23:03:09 2013 +0200
@@ -134,7 +134,6 @@
 
   // runtime entry points
   static void new_instance(JavaThread* thread, Klass* klass);
-  static void new_array(JavaThread* thread, Klass* klass, jint length);
   static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims);
 
   static void unimplemented_entry(JavaThread* thread, StubID id);
@@ -164,6 +163,7 @@
   static void log_object(JavaThread* thread, oop msg, jint flags);
 
  public:
+  static void new_array(JavaThread* thread, Klass* klass, jint length);
   // initialization
   static void initialize(BufferBlob* blob);