changeset 8311:5663e3c7eabe

Merge.
author Christian Humer <christian.humer@gmail.com>
date Fri, 15 Mar 2013 21:18:47 +0100
parents 89006c76f737 (current diff) 5115f468f8a4 (diff)
children b1dff27a1da6
files graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXDeoptimizationStub.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Code.java graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCode.java
diffstat 48 files changed, 1078 insertions(+), 954 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/VirtualObject.java	Fri Mar 15 21:18:47 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.api.code;
 
+import static com.oracle.graal.api.meta.MetaUtil.*;
+
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -65,31 +67,48 @@
         this.id = id;
     }
 
+    private static StringBuilder appendValue(StringBuilder buf, Value value, Set<VirtualObject> visited) {
+        if (value instanceof VirtualObject) {
+            VirtualObject vo = (VirtualObject) value;
+            buf.append("vobject:").append(toJavaName(vo.type, false)).append(':').append(vo.id);
+            if (!visited.contains(vo)) {
+                visited.add(vo);
+                buf.append('{');
+                if (vo.values == null) {
+                    buf.append("<uninitialized>");
+                } else {
+                    if (vo.type.isArray()) {
+                        for (int i = 0; i < vo.values.length; i++) {
+                            if (i != 0) {
+                                buf.append(',');
+                            }
+                            buf.append(i).append('=');
+                            appendValue(buf, vo.values[i], visited);
+                        }
+                    } else {
+                        ResolvedJavaField[] fields = vo.type.getInstanceFields(true);
+                        assert fields.length == vo.values.length : vo.type + ", fields=" + Arrays.toString(fields) + ", values=" + vo.values;
+                        for (int i = 0; i < vo.values.length; i++) {
+                            if (i != 0) {
+                                buf.append(',');
+                            }
+                            buf.append(fields[i].getName()).append('=');
+                            appendValue(buf, vo.values[i], visited);
+                        }
+                    }
+                }
+                buf.append('}');
+            }
+        } else {
+            buf.append(value);
+        }
+        return buf;
+    }
+
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder("vobject:").append(MetaUtil.toJavaName(type, false)).append(':').append(id).append('{');
-        if (values == null) {
-            buf.append("<uninitialized>");
-        } else {
-            if (type.isArray()) {
-                for (int i = 0; i < values.length; i++) {
-                    if (i != 0) {
-                        buf.append(',');
-                    }
-                    buf.append(i).append('=').append(values[i]);
-                }
-            } else {
-                ResolvedJavaField[] fields = type.getInstanceFields(true);
-                assert fields.length == values.length : type + ", fields=" + Arrays.toString(fields) + ", values=" + values;
-                for (int i = 0; i < values.length; i++) {
-                    if (i != 0) {
-                        buf.append(',');
-                    }
-                    buf.append(fields[i].getName()).append('=').append(values[i]);
-                }
-            }
-        }
-        return buf.append('}').toString();
+        Set<VirtualObject> visited = Collections.newSetFromMap(new IdentityHashMap<VirtualObject, Boolean>());
+        return appendValue(new StringBuilder(), this, visited).toString();
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java	Fri Mar 15 21:18:47 2013 +0100
@@ -30,7 +30,7 @@
 
     @Test
     public void test1() {
-        test("test1snippet", 2, 1, 0);
+        test("test1snippet", 3, 1, 0);
     }
 
     public static long test1snippet(long x) {
@@ -39,7 +39,7 @@
 
     @Test
     public void test2() {
-        test("test2snippet", 2, 0, 0);
+        test("test2snippet", 3, 0, 0);
     }
 
     public static long test2snippet(long x) {
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java	Fri Mar 15 21:18:33 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2011, 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.compiler.amd64;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.asm.*;
-
-public class AMD64DeoptimizationStub extends AMD64Code {
-
-    public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class);
-
-    public final Label label = new Label();
-    public final LIRFrameState info;
-    public final DeoptimizationAction action;
-    public final DeoptimizationReason reason;
-
-    public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
-        this.action = action;
-        this.reason = reason;
-        this.info = info;
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        Register scratch = tasm.frameMap.registerConfig.getScratchRegister();
-        masm.bind(label);
-        masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason));
-        AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE), info);
-    }
-
-    @Override
-    public String description() {
-        return "deopt stub[reason=" + reason + ", action=" + action + "]";
-    }
-}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Mar 15 21:18:47 2013 +0100
@@ -67,7 +67,6 @@
 import com.oracle.graal.lir.amd64.AMD64Move.MembarOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp;
-import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
@@ -255,23 +254,23 @@
     }
 
     @Override
-    public void emitJump(LabelRef label, LIRFrameState info) {
-        append(new JumpOp(label, info));
+    public void emitJump(LabelRef label) {
+        append(new JumpOp(label));
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.getKind().getStackKind()) {
             case Int:
             case Long:
             case Object:
-                append(new BranchOp(finalCondition, label, info));
+                append(new BranchOp(finalCondition, label));
                 break;
             case Float:
             case Double:
-                append(new FloatBranchOp(finalCondition, unorderedIsTrue, label, info));
+                append(new FloatBranchOp(finalCondition, unorderedIsTrue, label));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -279,14 +278,14 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef destination, LIRFrameState info, boolean negated) {
-        append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, destination, info));
+    public void emitOverflowCheckBranch(LabelRef destination, boolean negated) {
+        append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, destination));
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
         emitIntegerTest(left, right);
-        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label, info));
+        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label));
     }
 
     @Override
@@ -773,13 +772,6 @@
     }
 
     @Override
-    public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason) {
-        LIRFrameState info = state(reason);
-        LabelRef stubEntry = createDeoptStub(action, reason, info);
-        append(new BranchOp(ConditionFlag.Overflow, stubEntry, info));
-    }
-
-    @Override
     public void emitMembar(int barriers) {
         int necessaryBarriers = target.arch.requiredBarriers(barriers);
         if (target.isMP && necessaryBarriers != 0) {
@@ -899,29 +891,6 @@
     }
 
     @Override
-    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
-        assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate";
-        AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info);
-        lir.stubs.add(stub);
-        return LabelRef.forLabel(stub.label);
-    }
-
-    @Override
-    public void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
-        if (comp instanceof IsNullNode && negated) {
-            emitNullCheckGuard(((IsNullNode) comp).object());
-        } else {
-            super.emitGuardCheck(comp, deoptReason, action, negated);
-        }
-    }
-
-    private void emitNullCheckGuard(ValueNode object) {
-        Variable value = load(operand(object));
-        LIRFrameState info = state();
-        append(new NullCheckOp(value, info));
-    }
-
-    @Override
     public void visitCompareAndSwap(CompareAndSwapNode node) {
         Kind kind = node.newValue().kind();
         assert kind == node.expected().kind();
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Fri Mar 15 21:18:47 2013 +0100
@@ -31,7 +31,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 
 /**
  * PTX specific backend.
@@ -63,25 +62,22 @@
     }
 
     @Override
-    public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) {
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
         // Omit the frame if the method:
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
         // - has no instructions with debug info
-        boolean omitFrame = GraalOptions.CanOmitFrame && frameMap.frameSize() == frameMap.initialFrameSize && frameMap.registerConfig.getCalleeSaveLayout().registers.length == 0 &&
-                        !lir.hasArgInCallerFrame() && !lir.hasDebugInfo();
-
+        FrameMap frameMap = lirGen.frameMap;
         AbstractAssembler masm = new PTXAssembler(target, frameMap.registerConfig);
-        HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext();
-        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext);
+        HotSpotFrameContext frameContext = new HotSpotFrameContext();
+        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult);
         tasm.setFrameSize(frameMap.frameSize());
-        tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetToCustomArea());
         return tasm;
     }
 
     @Override
-    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir) {
+    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
         // Emit the prologue
         final String name = method.getName();
         Buffer codeBuffer = tasm.asm.codeBuffer;
@@ -103,7 +99,7 @@
         codeBuffer.emitString("  .reg .u32 %r<16>;");
 
         // Emit code for the LIR
-        lir.emitCode(tasm);
+        lirGen.lir.emitCode(tasm);
 
         // Emit the epilogue
         codeBuffer.emitString0("}");
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXDeoptimizationStub.java	Fri Mar 15 21:18:33 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * 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.compiler.ptx;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.*;
-import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.ptx.*;
-import com.oracle.graal.lir.asm.*;
-
-public class PTXDeoptimizationStub extends PTXCode {
-
-    public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class);
-    public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", true, void.class, Object.class);
-
-    public final Label label = new Label();
-    public final LIRFrameState info;
-    public final DeoptimizationAction action;
-    public final DeoptimizationReason reason;
-
-    public PTXDeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
-        this.action = action;
-        this.reason = reason;
-        this.info = info;
-    }
-
-    @Override
-    public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
-        masm.exit();
-    }
-
-    @Override
-    public String description() {
-        return "deopt stub[reason=" + reason + ", action=" + action + "]";
-    }
-}
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Mar 15 21:18:47 2013 +0100
@@ -179,20 +179,20 @@
     }
 
     @Override
-    public void emitJump(LabelRef label, LIRFrameState info) {
-        append(new JumpOp(label, info));
+    public void emitJump(LabelRef label) {
+        append(new JumpOp(label));
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
         switch (left.getKind().getStackKind()) {
             case Int:
                 append(new CompareOp(ICMP, cond, left, right));
-                append(new BranchOp(cond, label, info));
+                append(new BranchOp(cond, label));
                 break;
             case Object:
                 append(new CompareOp(ACMP, cond, left, right));
-                append(new BranchOp(cond, label, info));
+                append(new BranchOp(cond, label));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -200,12 +200,12 @@
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef label, LIRFrameState info, boolean negated) {
+    public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
         throw new InternalError("NYI");
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
         throw new InternalError("NYI");
     }
 
@@ -349,11 +349,6 @@
     }
 
     @Override
-    public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
     public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
         append(new ReturnOp(Value.ILLEGAL));
     }
@@ -453,14 +448,6 @@
     }
 
     @Override
-    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
-        assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate";
-        PTXDeoptimizationStub stub = new PTXDeoptimizationStub(action, reason, info);
-        lir.stubs.add(stub);
-        return LabelRef.forLabel(stub.label);
-    }
-
-    @Override
     public void visitCompareAndSwap(CompareAndSwapNode node) {
         throw new InternalError("NYI");
     }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Mar 15 21:18:47 2013 +0100
@@ -62,7 +62,7 @@
     }
 
     @Override
-    public void emitJump(LabelRef label, LIRFrameState info) {
+    public void emitJump(LabelRef label) {
         @SuppressWarnings("unused")
         SPARCLIRInstruction instruction = null;
         // SPARC: Auto-generated method stub
@@ -70,19 +70,19 @@
     }
 
     @Override
-    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
         // SPARC: Auto-generated method stub
 
     }
 
     @Override
-    public void emitOverflowCheckBranch(LabelRef label, LIRFrameState info, boolean negated) {
+    public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
         // SPARC: Auto-generated method stub
 
     }
 
     @Override
-    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
         // SPARC: Auto-generated method stub
 
     }
@@ -118,12 +118,6 @@
     }
 
     @Override
-    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
-        // SPARC: Auto-generated method stub
-        return null;
-    }
-
-    @Override
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
         // SPARC: Auto-generated method stub
 
@@ -340,12 +334,6 @@
     }
 
     @Override
-    public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason) {
-        // SPARC: Auto-generated method stub
-
-    }
-
-    @Override
     public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
         // SPARC: Auto-generated method stub
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Mar 15 21:18:47 2013 +0100
@@ -51,9 +51,10 @@
                     final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) {
         assert (method.getModifiers() & Modifier.NATIVE) == 0 : "compiling native methods is not supported";
 
-        return Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Callable<CompilationResult>() {
+        final CompilationResult compilationResult = new CompilationResult();
+        Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Runnable() {
 
-            public CompilationResult call() {
+            public void run() {
                 final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions);
                 final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() {
 
@@ -61,21 +62,23 @@
                         return emitHIR(runtime, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog);
                     }
                 });
-                final FrameMap frameMap = Debug.scope("BackEnd", lir, new Callable<FrameMap>() {
+                final LIRGenerator lirGen = Debug.scope("BackEnd", lir, new Callable<LIRGenerator>() {
 
-                    public FrameMap call() {
+                    public LIRGenerator call() {
                         return emitLIR(backend, target, lir, graph, method);
                     }
                 });
-                return Debug.scope("CodeGen", frameMap, new Callable<CompilationResult>() {
+                Debug.scope("CodeGen", lirGen, new Runnable() {
 
-                    public CompilationResult call() {
-                        return emitCode(backend, getLeafGraphIdArray(graph), assumptions, method, lir, frameMap);
+                    public void run() {
+                        emitCode(backend, getLeafGraphIdArray(graph), assumptions, method, lirGen, compilationResult);
                     }
 
                 });
             }
         });
+
+        return compilationResult;
     }
 
     private static long[] getLeafGraphIdArray(StructuredGraph graph) {
@@ -201,7 +204,7 @@
 
         plan.runPhases(PhasePosition.LOW_LEVEL, graph);
 
-        new GuardLoweringPhase().apply(graph);
+        new GuardLoweringPhase(target).apply(graph);
 
         // Add safepoints to loops
         new SafepointInsertionPhase().apply(graph);
@@ -233,11 +236,11 @@
 
     }
 
-    public static FrameMap emitLIR(Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) {
+    public static LIRGenerator emitLIR(Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, final ResolvedJavaMethod method) {
         final FrameMap frameMap = backend.newFrameMap();
-        final LIRGenerator lirGenerator = backend.newLIRGenerator(graph, frameMap, method, lir);
+        final LIRGenerator lirGen = backend.newLIRGenerator(graph, frameMap, method, lir);
 
-        Debug.scope("LIRGen", lirGenerator, new Runnable() {
+        Debug.scope("LIRGen", lirGen, new Runnable() {
 
             public void run() {
                 for (Block b : lir.linearScanOrder()) {
@@ -254,23 +257,25 @@
                             emitBlock(pred);
                         }
                     }
-                    lirGenerator.doBlock(b);
+                    lirGen.doBlock(b);
                 }
             }
         });
 
+        lirGen.beforeRegisterAllocation();
+
         Debug.scope("Allocator", new Runnable() {
 
             public void run() {
-                new LinearScan(target, method, lir, lirGenerator, frameMap).allocate();
+                new LinearScan(target, method, lir, lirGen, frameMap).allocate();
             }
         });
-        return frameMap;
+        return lirGen;
     }
 
-    public static CompilationResult emitCode(Backend backend, long[] leafGraphIds, Assumptions assumptions, ResolvedJavaMethod method, LIR lir, FrameMap frameMap) {
-        TargetMethodAssembler tasm = backend.newAssembler(frameMap, lir);
-        backend.emitCode(tasm, method, lir);
+    public static void emitCode(Backend backend, long[] leafGraphIds, Assumptions assumptions, ResolvedJavaMethod method, LIRGenerator lirGen, CompilationResult compilationResult) {
+        TargetMethodAssembler tasm = backend.newAssembler(lirGen, compilationResult);
+        backend.emitCode(tasm, method, lirGen);
         CompilationResult result = tasm.finishTargetMethod(method, false);
         if (!assumptions.isEmpty()) {
             result.setAssumptions(assumptions);
@@ -278,6 +283,5 @@
         result.setLeafGraphIds(leafGraphIds);
 
         Debug.dump(result, "After code generation");
-        return result;
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Mar 15 21:18:47 2013 +0100
@@ -54,17 +54,18 @@
  */
 public abstract class LIRGenerator extends LIRGeneratorTool {
 
+    public final FrameMap frameMap;
+    public final NodeMap<Value> nodeOperands;
+    public final LIR lir;
+
     protected final StructuredGraph graph;
     protected final CodeCacheProvider runtime;
     protected final TargetDescription target;
     protected final ResolvedJavaMethod method;
-    protected final FrameMap frameMap;
-    public final NodeMap<Value> nodeOperands;
 
-    protected final LIR lir;
     private final DebugInfoBuilder debugInfoBuilder;
 
-    private Block currentBlock;
+    protected Block currentBlock;
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
     private FrameState lastState;
@@ -349,27 +350,6 @@
         List<ScheduledNode> nodes = lir.nodesFor(block);
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
-
-            if (GraalOptions.OptImplicitNullChecks) {
-                Node nextInstr = null;
-                if (i < nodes.size() - 1) {
-                    nextInstr = nodes.get(i + 1);
-                }
-
-                if (instr instanceof GuardNode) {
-                    GuardNode guardNode = (GuardNode) instr;
-                    if (guardNode.condition() instanceof IsNullNode && guardNode.negated()) {
-                        IsNullNode isNullNode = (IsNullNode) guardNode.condition();
-                        if (nextInstr instanceof Access) {
-                            Access access = (Access) nextInstr;
-                            if (isNullNode.object() == access.object() && canBeNullCheck(access.location())) {
-                                access.setNullCheck(true);
-                                continue;
-                            }
-                        }
-                    }
-                }
-            }
             if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
                 TTY.println("LIRGen for " + instr);
             }
@@ -410,7 +390,7 @@
             NodeClassIterable successors = block.getEndNode().successors();
             assert successors.isNotEmpty() : "should have at least one successor : " + block.getEndNode();
 
-            emitJump(getLIRBlock((FixedNode) successors.first()), null);
+            emitJump(getLIRBlock((FixedNode) successors.first()));
         }
 
         if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
@@ -469,10 +449,6 @@
         ((LIRLowerable) node).generate(this);
     }
 
-    private boolean canBeNullCheck(LocationNode location) {
-        return !(location instanceof IndexedLocationNode) && location.displacement() < this.target().implicitNullCheckLimit;
-    }
-
     protected CallingConvention createCallingConvention() {
         return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), MetaUtil.signatureToTypes(method), target, false);
     }
@@ -571,7 +547,7 @@
         }
         resolver.dispose();
 
-        append(new JumpOp(getLIRBlock(merge), null));
+        append(new JumpOp(getLIRBlock(merge)));
     }
 
     private Value operandForPhi(PhiNode phi) {
@@ -589,89 +565,46 @@
 
     @Override
     public void emitIf(IfNode x) {
-        emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()), null);
+        emitBranch(x.condition(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()));
     }
 
-    @Override
-    public void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
-        if (comp instanceof LogicConstantNode && ((LogicConstantNode) comp).getValue() != negated) {
-            // True constant, nothing to emit.
-            // False constants are handled within emitBranch.
-        } else {
-            // Fall back to a normal branch.
-            LIRFrameState info = state(deoptReason);
-            LabelRef stubEntry = createDeoptStub(action, deoptReason, info);
-            if (negated) {
-                emitBranch(comp, stubEntry, null, info);
-            } else {
-                emitBranch(comp, null, stubEntry, info);
-            }
-        }
-    }
-
-    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
+    public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor) {
         if (node instanceof IsNullNode) {
-            emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, info);
+            emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor);
         } else if (node instanceof CompareNode) {
-            emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, info);
+            emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor);
         } else if (node instanceof LogicConstantNode) {
-            emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor, info);
+            emitConstantBranch(((LogicConstantNode) node).getValue(), trueSuccessor, falseSuccessor);
         } else if (node instanceof IntegerTestNode) {
-            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, info);
+            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor);
         } else {
             throw GraalInternalError.unimplemented(node.toString());
         }
     }
 
-    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
-        if (falseSuccessor != null) {
-            emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info);
-            if (trueSuccessor != null) {
-                emitJump(trueSuccessor, null);
-            }
-        } else {
-            emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, info);
-        }
+    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+        emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor);
+        emitJump(trueSuccessor);
     }
 
-    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
-        if (falseSuccessorBlock != null) {
-            emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info);
-            if (trueSuccessorBlock != null) {
-                emitJump(trueSuccessorBlock, null);
-            }
-        } else {
-            emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessorBlock, info);
-        }
+    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
+        emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock);
+        emitJump(trueSuccessorBlock);
     }
 
-    public void emitOverflowCheckBranch(LabelRef noOverflowBlock, LabelRef overflowBlock, LIRFrameState info) {
-        if (overflowBlock != null) {
-            emitOverflowCheckBranch(overflowBlock, info, false);
-            if (noOverflowBlock != null) {
-                emitJump(noOverflowBlock, null);
-            }
-        } else {
-            emitOverflowCheckBranch(noOverflowBlock, info, true);
-        }
+    public void emitOverflowCheckBranch(LabelRef noOverflowBlock, LabelRef overflowBlock) {
+        emitOverflowCheckBranch(overflowBlock, false);
+        emitJump(noOverflowBlock);
     }
 
-    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
-        if (falseSuccessorBlock != null) {
-            emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock, info);
-            if (trueSuccessorBlock != null) {
-                emitJump(trueSuccessorBlock, null);
-            }
-        } else {
-            emitIntegerTestBranch(operand(test.x()), operand(test.y()), false, trueSuccessorBlock, info);
-        }
+    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
+        emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock);
+        emitJump(trueSuccessorBlock);
     }
 
-    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
+    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
         LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock;
-        if (block != null) {
-            emitJump(block, info);
-        }
+        emitJump(block);
     }
 
     @Override
@@ -698,13 +631,13 @@
         }
     }
 
-    public abstract void emitJump(LabelRef label, LIRFrameState info);
+    public abstract void emitJump(LabelRef label);
 
-    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info);
+    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label);
 
-    public abstract void emitOverflowCheckBranch(LabelRef label, LIRFrameState info, boolean negated);
+    public abstract void emitOverflowCheckBranch(LabelRef label, boolean negated);
 
-    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info);
+    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label);
 
     public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
 
@@ -744,7 +677,7 @@
 
     protected abstract void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info);
 
-    private static Value toStackKind(Value value) {
+    protected static Value toStackKind(Value value) {
         if (value.getKind().getStackKind() != value.getKind()) {
             // We only have stack-kinds in the LIR, so convert the operand kind for values from the
             // calling convention.
@@ -776,8 +709,6 @@
         return result;
     }
 
-    protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info);
-
     @Override
     public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args) {
         LIRFrameState info = canTrap ? state() : null;
@@ -846,7 +777,7 @@
     public void emitSwitch(SwitchNode x) {
         int keyCount = x.keyCount();
         if (keyCount == 0) {
-            emitJump(getLIRBlock(x.defaultSuccessor()), null);
+            emitJump(getLIRBlock(x.defaultSuccessor()));
         } else {
             Variable value = load(operand(x.value()));
             LabelRef defaultTarget = x.defaultSuccessor() == null ? null : getLIRBlock(x.defaultSuccessor());
@@ -858,7 +789,7 @@
                 long valueRange = x.keyAt(keyCount - 1).asLong() - x.keyAt(0).asLong() + 1;
                 int switchRangeCount = switchRangeCount(x);
                 if (switchRangeCount == 0) {
-                    emitJump(getLIRBlock(x.defaultSuccessor()), null);
+                    emitJump(getLIRBlock(x.defaultSuccessor()));
                 } else if (switchRangeCount >= GraalOptions.MinimumJumpTableSize && keyCount / (double) valueRange >= GraalOptions.MinTableSwitchDensity) {
                     int minValue = x.keyAt(0).asInt();
                     assert valueRange < Integer.MAX_VALUE;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Fri Mar 15 21:18:47 2013 +0100
@@ -52,16 +52,13 @@
 
     public abstract LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir);
 
-    public abstract TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir);
+    public abstract TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult);
 
     /**
      * Emits the code for a given method. This includes any architecture/runtime specific
      * prefix/suffix. A prefix typically contains the code for setting up the frame, spilling
      * callee-save registers, stack overflow checking, handling multiple entry points etc. A suffix
      * may contain out-of-line stubs and method end guard instructions.
-     * 
-     * @param method the method associated with {@code lir}
-     * @param lir the LIR of {@code method}
      */
-    public abstract void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir);
+    public abstract void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen);
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Mar 15 21:18:47 2013 +0100
@@ -25,6 +25,7 @@
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.CallingConvention.Type.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
 import java.lang.reflect.*;
 
@@ -36,22 +37,15 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.compiler.amd64.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
 import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.phases.*;
 
 /**
@@ -73,122 +67,6 @@
         return new HotSpotAMD64LIRGenerator(graph, runtime(), target, frameMap, method, lir);
     }
 
-    static final class HotSpotAMD64LIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator {
-
-        private HotSpotRuntime runtime() {
-            return (HotSpotRuntime) runtime;
-        }
-
-        private HotSpotAMD64LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-            super(graph, runtime, target, frameMap, method, lir);
-        }
-
-        @Override
-        protected boolean needOnlyOopMaps() {
-            // Stubs only need oop maps
-            return runtime().asStub(method) != null;
-        }
-
-        @Override
-        protected CallingConvention createCallingConvention() {
-            Stub stub = runtime().asStub(method);
-            if (stub != null) {
-                return stub.getLinkage().getCallingConvention();
-            }
-
-            if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
-                return super.createCallingConvention();
-            } else {
-                return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), new JavaType[]{runtime.lookupJavaType(long.class)}, target, false);
-            }
-        }
-
-        @Override
-        public void visitSafepointNode(SafepointNode i) {
-            LIRFrameState info = state();
-            append(new AMD64SafepointOp(info, runtime().config, this));
-        }
-
-        @Override
-        public void visitExceptionObject(ExceptionObjectNode x) {
-            HotSpotVMConfig config = runtime().config;
-            RegisterValue thread = runtime().threadRegister().asValue();
-            Value exception = emitLoad(Kind.Object, thread, config.threadExceptionOopOffset, Value.ILLEGAL, 0, false);
-            emitStore(Kind.Object, thread, config.threadExceptionOopOffset, Value.ILLEGAL, 0, Constant.NULL_OBJECT, false);
-            emitStore(Kind.Long, thread, config.threadExceptionPcOffset, Value.ILLEGAL, 0, Constant.LONG_0, false);
-            setResult(x, exception);
-        }
-
-        @SuppressWarnings("hiding")
-        @Override
-        public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
-            Kind kind = x.newValue().kind();
-            assert kind == x.expectedValue().kind();
-
-            Value expected = loadNonConst(operand(x.expectedValue()));
-            Variable newVal = load(operand(x.newValue()));
-
-            int disp = 0;
-            AMD64AddressValue address;
-            Value index = operand(x.offset());
-            if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) {
-                assert !runtime.needsDataPatch(asConstant(index));
-                disp += (int) ValueUtil.asConstant(index).asLong();
-                address = new AMD64AddressValue(kind, load(operand(x.object())), disp);
-            } else {
-                address = new AMD64AddressValue(kind, load(operand(x.object())), load(index), Scale.Times1, disp);
-            }
-
-            RegisterValue rax = AMD64.rax.asValue(kind);
-            emitMove(rax, expected);
-            append(new CompareAndSwapOp(rax, address, rax, newVal));
-
-            Variable result = newVariable(x.kind());
-            emitMove(result, rax);
-            setResult(x, result);
-        }
-
-        @Override
-        public void emitTailcall(Value[] args, Value address) {
-            append(new AMD64TailcallOp(args, address));
-
-        }
-
-        @Override
-        protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-            InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
-            if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
-                append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
-            } else {
-                assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
-                HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
-                Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
-                append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
-            }
-        }
-
-        @Override
-        protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-            Value metaspaceMethod = AMD64.rbx.asValue();
-            emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
-            Value targetAddress = AMD64.rax.asValue();
-            emitMove(targetAddress, operand(callTarget.computedAddress()));
-            append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
-        }
-
-        @Override
-        public void emitUnwind(Value exception) {
-            RegisterValue exceptionParameter = AMD64.rax.asValue();
-            emitMove(exceptionParameter, exception);
-            append(new AMD64HotSpotUnwindOp(exceptionParameter));
-        }
-
-        @Override
-        public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
-            append(new AMD64DeoptimizeOp(action, reason, state(reason)));
-        }
-    }
-
     /**
      * Emits code to do stack overflow checking.
      * 
@@ -224,8 +102,7 @@
 
             AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
             emitStackOverflowCheck(tasm, false);
-            asm.push(rbp);
-            asm.decrementq(rsp, frameSize - 8); // account for the push of RBP above
+            asm.decrementq(rsp, frameSize);
             if (GraalOptions.ZapStackOnMethodEntry) {
                 final int intSize = 4;
                 for (int i = 0; i < frameSize / intSize; ++i) {
@@ -253,31 +130,35 @@
                 asm.restore(csl, frameToCSA);
             }
 
-            asm.incrementq(rsp, frameSize - 8); // account for the pop of RBP below
-            asm.pop(rbp);
+            asm.incrementq(rsp, frameSize);
         }
     }
 
     @Override
-    public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) {
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
         // Omit the frame if the method:
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
         // - has no instructions with debug info
-        boolean omitFrame = GraalOptions.CanOmitFrame && frameMap.frameSize() == frameMap.initialFrameSize && frameMap.registerConfig.getCalleeSaveLayout().registers.length == 0 &&
-                        !lir.hasArgInCallerFrame() && !lir.hasDebugInfo();
+        HotSpotAMD64LIRGenerator gen = (HotSpotAMD64LIRGenerator) lirGen;
+        FrameMap frameMap = gen.frameMap;
+        LIR lir = gen.lir;
+        boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
 
         AbstractAssembler masm = new AMD64MacroAssembler(target, frameMap.registerConfig);
         HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext();
-        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext);
+        TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult);
         tasm.setFrameSize(frameMap.frameSize());
-        tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetToCustomArea());
+        StackSlot deoptimizationRescueSlot = gen.deoptimizationRescueSlot;
+        if (deoptimizationRescueSlot != null) {
+            tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot));
+        }
         return tasm;
     }
 
     @Override
-    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir) {
+    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
         AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
         FrameMap frameMap = tasm.frameMap;
         RegisterConfig regConfig = frameMap.registerConfig;
@@ -304,7 +185,7 @@
         tasm.recordMark(Marks.MARK_VERIFIED_ENTRY);
 
         // Emit code for the LIR
-        lir.emitCode(tasm);
+        lirGen.lir.emitCode(tasm);
 
         boolean frameOmitted = tasm.frameContext == null;
         if (!frameOmitted) {
@@ -316,7 +197,7 @@
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
-            assert !frameMap.accessesCallerFrame();
+            assert !frameMap.accessesCallerFrame() : method;
         }
 
         if (unverifiedStub != null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Fri Mar 15 21:18:47 2013 +0100
@@ -0,0 +1,45 @@
+/*
+ * 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.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.amd64.*;
+
+/**
+ * Superclass for operations that use the value of RBP saved in a method's prologue.
+ */
+abstract class AMD64HotSpotEpilogueOp extends AMD64LIRInstruction {
+
+    /**
+     * The type of location (i.e., stack or register) in which RBP is saved is not known until
+     * initial LIR generation is finished. Until then, we use a placeholder variable so that LIR
+     * verification is successful.
+     */
+    private static final Variable PLACEHOLDER = new Variable(Kind.Long, Integer.MAX_VALUE, Register.RegisterFlag.CPU);
+
+    @Use({REG, STACK}) protected AllocatableValue savedRbp = PLACEHOLDER;
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Mar 15 21:18:47 2013 +0100
@@ -111,12 +111,7 @@
             };
             csl = new CalleeSaveLayout(0, -1, 8, regs);
         } else {
-            // We reserve space for saving RBP but don't explicitly specify
-            // it as a callee save register since we explicitly do the saving
-            // with push and pop in HotSpotFrameContext
-            final int size = 8;
-            final Register[] regs = {};
-            csl = new CalleeSaveLayout(0, size, 8, regs);
+            csl = null;
         }
 
         attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Fri Mar 15 21:18:47 2013 +0100
@@ -0,0 +1,63 @@
+/*
+ * 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.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Performs an unwind to throw an exception.
+ */
+@Opcode("RETURN")
+final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp {
+
+    @Use({REG, ILLEGAL}) protected Value value;
+
+    AMD64HotSpotReturnOp(Value value) {
+        this.value = value;
+    }
+
+    @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);
+        }
+        masm.ret(0);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java	Fri Mar 15 21:18:47 2013 +0100
@@ -25,6 +25,7 @@
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*;
 import static com.oracle.graal.hotspot.amd64.AMD64DeoptimizeOp.*;
+import static com.oracle.graal.hotspot.amd64.AMD64HotSpotUnwindOp.*;
 import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
@@ -46,11 +47,11 @@
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.hotspot.amd64.snippets.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.snippets.*;
+import com.oracle.graal.snippets.amd64.*;
 
 public class AMD64HotSpotRuntime extends HotSpotRuntime {
 
@@ -60,10 +61,10 @@
         Kind word = graalRuntime.getTarget().wordKind;
 
         // @formatter:off
-        addRuntimeCall(AMD64HotSpotUnwindOp.UNWIND_EXCEPTION, config.unwindExceptionStub,
-                        /*           temps */ null,
-                        /*             ret */ ret(Kind.Void),
-                        /* arg0: exception */ javaCallingConvention(Kind.Object));
+        addRuntimeCall(UNWIND_EXCEPTION, config.unwindExceptionStub,
+               /*           temps */ null,
+               /*             ret */ ret(Kind.Void),
+               /* arg0: exception */ rax.asValue(Kind.Object));
 
         addRuntimeCall(DEOPTIMIZE, config.deoptimizeStub,
                 /*           temps */ null,
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Fri Mar 15 21:18:47 2013 +0100
@@ -23,11 +23,12 @@
 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.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.RuntimeCallTarget.*;
+import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
@@ -36,24 +37,39 @@
 /**
  * Performs an unwind to throw an exception.
  */
-@Opcode("CALL_INDIRECT")
-final class AMD64HotSpotUnwindOp extends AMD64LIRInstruction {
+@Opcode("UNWIND")
+final class AMD64HotSpotUnwindOp extends AMD64HotSpotEpilogueOp {
 
     public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, void.class, Object.class);
 
+    /**
+     * Unwind stub expects the exception in RAX.
+     */
+    public static final Register EXCEPTION = AMD64.rax;
+
     @Use({REG}) protected AllocatableValue exception;
-    @Temp private RegisterValue framePointer;
 
     AMD64HotSpotUnwindOp(AllocatableValue exception) {
         this.exception = exception;
-        assert exception == AMD64.rax.asValue();
-        framePointer = AMD64.rbp.asValue();
+        assert asRegister(exception) == EXCEPTION;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        masm.movq(framePointer.getRegister(), rsp);
-        masm.incrementq(framePointer.getRegister(), tasm.frameMap.frameSize() - 8);
+        // Copy the saved RBP value into the slot just below the return address
+        // so that the stub can pick it up from there.
+        AMD64Address rbpSlot;
+        int rbpSlotOffset = tasm.frameMap.frameSize() - 8;
+        if (isStackSlot(savedRbp)) {
+            rbpSlot = (AMD64Address) tasm.asAddress(savedRbp);
+            assert rbpSlot.getDisplacement() == rbpSlotOffset;
+        } else {
+            rbpSlot = new AMD64Address(rsp, rbpSlotOffset);
+            masm.movq(rbpSlot, asRegister(savedRbp));
+        }
+
+        // Pass the address of the RBP slot in RBP itself
+        masm.leaq(rbp, rbpSlot);
         AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(UNWIND_EXCEPTION), null);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/HotSpotAMD64LIRGenerator.java	Fri Mar 15 21:18:47 2013 +0100
@@ -0,0 +1,255 @@
+/*
+ * 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.CallingConvention.Type.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.hotspot.amd64.AMD64HotSpotUnwindOp.*;
+
+import java.util.*;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.amd64.AMD64Address.*;
+import com.oracle.graal.compiler.amd64.*;
+import com.oracle.graal.hotspot.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.hotspot.stubs.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64Move.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.*;
+
+/**
+ * LIR generator specialized for AMD64 HotSpot.
+ */
+final class HotSpotAMD64LIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator {
+
+    private HotSpotRuntime runtime() {
+        return (HotSpotRuntime) runtime;
+    }
+
+    HotSpotAMD64LIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
+        super(graph, runtime, target, frameMap, method, lir);
+    }
+
+    /**
+     * The slot reserved for storing the original return address when a frame is marked for
+     * deoptimization. The return address slot in the callee is overwritten with the address of a
+     * deoptimization stub.
+     */
+    StackSlot deoptimizationRescueSlot;
+
+    /**
+     * The position at which the instruction for saving RBP should be inserted.
+     */
+    Block saveRbpBlock;
+    int saveRbpIndex;
+
+    /**
+     * The slot reserved for saving RBP.
+     */
+    StackSlot rbpSlot;
+
+    /**
+     * List of epilogue operations that need to restore RBP.
+     */
+    List<AMD64HotSpotEpilogueOp> epilogueOps = new ArrayList<>(2);
+
+    @Override
+    protected void emitPrologue() {
+
+        CallingConvention incomingArguments = createCallingConvention();
+
+        RegisterValue rbpParam = rbp.asValue(Kind.Long);
+        Value[] params = new Value[incomingArguments.getArgumentCount() + 1];
+        for (int i = 0; i < params.length - 1; i++) {
+            params[i] = toStackKind(incomingArguments.getArgument(i));
+            if (isStackSlot(params[i])) {
+                StackSlot slot = ValueUtil.asStackSlot(params[i]);
+                if (slot.isInCallerFrame() && !lir.hasArgInCallerFrame()) {
+                    lir.setHasArgInCallerFrame();
+                }
+            }
+        }
+        params[params.length - 1] = rbpParam;
+
+        ParametersOp paramsOp = new ParametersOp(params);
+        append(paramsOp);
+        saveRbpBlock = currentBlock;
+        saveRbpIndex = lir.lir(saveRbpBlock).size();
+        append(paramsOp); // placeholder
+        rbpSlot = frameMap.allocateSpillSlot(Kind.Long);
+        assert rbpSlot.getRawOffset() == -16 : rbpSlot.getRawOffset();
+
+        for (LocalNode local : graph.getNodes(LocalNode.class)) {
+            Value param = params[local.index()];
+            assert param.getKind() == local.kind().getStackKind();
+            setResult(local, emitMove(param));
+        }
+    }
+
+    @Override
+    protected void emitReturn(Value input) {
+        AMD64HotSpotReturnOp op = new AMD64HotSpotReturnOp(input);
+        epilogueOps.add(op);
+        append(op);
+    }
+
+    @Override
+    protected boolean needOnlyOopMaps() {
+        // Stubs only need oop maps
+        return runtime().asStub(method) != null;
+    }
+
+    @Override
+    protected CallingConvention createCallingConvention() {
+        Stub stub = runtime().asStub(method);
+        if (stub != null) {
+            return stub.getLinkage().getCallingConvention();
+        }
+
+        if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) {
+            return super.createCallingConvention();
+        } else {
+            return frameMap.registerConfig.getCallingConvention(JavaCallee, method.getSignature().getReturnType(null), new JavaType[]{runtime.lookupJavaType(long.class)}, target, false);
+        }
+    }
+
+    @Override
+    public void visitSafepointNode(SafepointNode i) {
+        LIRFrameState info = state();
+        append(new AMD64SafepointOp(info, runtime().config, this));
+    }
+
+    @Override
+    public void visitExceptionObject(ExceptionObjectNode x) {
+        HotSpotVMConfig config = runtime().config;
+        RegisterValue thread = runtime().threadRegister().asValue();
+        Value exception = emitLoad(Kind.Object, thread, config.threadExceptionOopOffset, Value.ILLEGAL, 0, false);
+        emitStore(Kind.Object, thread, config.threadExceptionOopOffset, Value.ILLEGAL, 0, Constant.NULL_OBJECT, false);
+        emitStore(Kind.Long, thread, config.threadExceptionPcOffset, Value.ILLEGAL, 0, Constant.LONG_0, false);
+        setResult(x, exception);
+    }
+
+    @SuppressWarnings("hiding")
+    @Override
+    public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) {
+        Kind kind = x.newValue().kind();
+        assert kind == x.expectedValue().kind();
+
+        Value expected = loadNonConst(operand(x.expectedValue()));
+        Variable newVal = load(operand(x.newValue()));
+
+        int disp = 0;
+        AMD64AddressValue address;
+        Value index = operand(x.offset());
+        if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) {
+            assert !runtime.needsDataPatch(asConstant(index));
+            disp += (int) ValueUtil.asConstant(index).asLong();
+            address = new AMD64AddressValue(kind, load(operand(x.object())), disp);
+        } else {
+            address = new AMD64AddressValue(kind, load(operand(x.object())), load(index), Scale.Times1, disp);
+        }
+
+        RegisterValue rax = AMD64.rax.asValue(kind);
+        emitMove(rax, expected);
+        append(new CompareAndSwapOp(rax, address, rax, newVal));
+
+        Variable result = newVariable(x.kind());
+        emitMove(result, rax);
+        setResult(x, result);
+    }
+
+    @Override
+    public void emitTailcall(Value[] args, Value address) {
+        append(new AMD64TailcallOp(args, address));
+
+    }
+
+    @Override
+    protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind();
+        if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) {
+            append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind));
+        } else {
+            assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
+            HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
+            Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
+            append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
+        }
+    }
+
+    @Override
+    protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
+        Value metaspaceMethod = AMD64.rbx.asValue();
+        emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
+        Value targetAddress = AMD64.rax.asValue();
+        emitMove(targetAddress, operand(callTarget.computedAddress()));
+        append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
+    }
+
+    @Override
+    public void emitUnwind(Value exception) {
+        RegisterValue exceptionParameter = EXCEPTION.asValue();
+        emitMove(exceptionParameter, exception);
+        AMD64HotSpotUnwindOp op = new AMD64HotSpotUnwindOp(exceptionParameter);
+        epilogueOps.add(op);
+        append(op);
+    }
+
+    @Override
+    public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
+        append(new AMD64DeoptimizeOp(action, reason, state()));
+    }
+
+    @Override
+    public void beforeRegisterAllocation() {
+        assert rbpSlot != null;
+        RegisterValue rbpParam = rbp.asValue(Kind.Long);
+        AllocatableValue savedRbp;
+        LIRInstruction saveRbp;
+        if (lir.hasDebugInfo()) {
+            savedRbp = rbpSlot;
+            deoptimizationRescueSlot = frameMap.allocateSpillSlot(Kind.Long);
+        } else {
+            frameMap.freeSpillSlot(rbpSlot);
+            savedRbp = newVariable(Kind.Long);
+        }
+
+        for (AMD64HotSpotEpilogueOp op : epilogueOps) {
+            op.savedRbp = savedRbp;
+        }
+
+        saveRbp = new MoveFromRegOp(savedRbp, rbpParam);
+        lir.lir(saveRbpBlock).set(saveRbpIndex, saveRbp);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java	Fri Mar 15 21:18:33 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-/*
- * 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.hotspot.amd64.snippets;
-
-import static com.oracle.graal.snippets.SnippetTemplate.*;
-import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
-import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.calc.ConvertNode.Op;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.snippets.*;
-import com.oracle.graal.snippets.Snippet.Parameter;
-import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates;
-import com.oracle.graal.snippets.SnippetTemplate.Arguments;
-import com.oracle.graal.snippets.SnippetTemplate.Key;
-
-/**
- * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match
- * the semantics of the JVM specification.
- */
-public class AMD64ConvertSnippets implements SnippetsInterface {
-
-    /**
-     * Converts a float to an int.
-     * <p>
-     * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the
-     * conversion. If the float value is a NaN, infinity or if the result of the conversion is
-     * larger than {@link Integer#MAX_VALUE} then CVTTSS2SI returns {@link Integer#MIN_VALUE} and
-     * extra tests are required on the float value to return the correct int value.
-     * 
-     * @param input the float being converted
-     * @param result the result produced by the CVTTSS2SI instruction
-     */
-    @Snippet
-    public static int f2i(@Parameter("input") float input, @Parameter("result") int result) {
-        if (result == Integer.MIN_VALUE) {
-            probability(NOT_FREQUENT_PROBABILITY);
-            if (Float.isNaN(input)) {
-                // input is NaN -> return 0
-                return 0;
-            } else if (input > 0.0f) {
-                // input is > 0 -> return max int
-                return Integer.MAX_VALUE;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Converts a float to a long.
-     * <p>
-     * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the
-     * conversion. If the float value is a NaN or infinity then CVTTSS2SI returns
-     * {@link Long#MIN_VALUE} and extra tests are required on the float value to return the correct
-     * long value.
-     * 
-     * @param input the float being converted
-     * @param result the result produced by the CVTTSS2SI instruction
-     */
-    @Snippet
-    public static long f2l(@Parameter("input") float input, @Parameter("result") long result) {
-        if (result == Long.MIN_VALUE) {
-            probability(NOT_FREQUENT_PROBABILITY);
-            if (Float.isNaN(input)) {
-                // input is NaN -> return 0
-                return 0;
-            } else if (input > 0.0f) {
-                // input is > 0 -> return max int
-                return Long.MAX_VALUE;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Converts a double to an int.
-     * <p>
-     * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the
-     * conversion. If the double value is a NaN, infinity or if the result of the conversion is
-     * larger than {@link Integer#MAX_VALUE} then CVTTSD2SI returns {@link Integer#MIN_VALUE} and
-     * extra tests are required on the double value to return the correct int value.
-     * 
-     * @param input the double being converted
-     * @param result the result produced by the CVTTSS2SI instruction
-     */
-    @Snippet
-    public static int d2i(@Parameter("input") double input, @Parameter("result") int result) {
-        if (result == Integer.MIN_VALUE) {
-            probability(NOT_FREQUENT_PROBABILITY);
-            if (Double.isNaN(input)) {
-                // input is NaN -> return 0
-                return 0;
-            } else if (input > 0.0d) {
-                // input is positive -> return maxInt
-                return Integer.MAX_VALUE;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Converts a double to a long.
-     * <p>
-     * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the
-     * conversion. If the double value is a NaN, infinity or if the result of the conversion is
-     * larger than {@link Long#MAX_VALUE} then CVTTSD2SI returns {@link Long#MIN_VALUE} and extra
-     * tests are required on the double value to return the correct long value.
-     * 
-     * @param input the double being converted
-     * @param result the result produced by the CVTTSS2SI instruction
-     */
-    @Snippet
-    public static long d2l(@Parameter("input") double input, @Parameter("result") long result) {
-        if (result == Long.MIN_VALUE) {
-            probability(NOT_FREQUENT_PROBABILITY);
-            if (Double.isNaN(input)) {
-                // input is NaN -> return 0
-                return 0;
-            } else if (input > 0.0d) {
-                // input is positive -> return maxInt
-                return Long.MAX_VALUE;
-            }
-        }
-        return result;
-    }
-
-    public static class Templates extends AbstractTemplates<AMD64ConvertSnippets> {
-
-        private final ResolvedJavaMethod f2i;
-        private final ResolvedJavaMethod f2l;
-        private final ResolvedJavaMethod d2i;
-        private final ResolvedJavaMethod d2l;
-
-        public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) {
-            super(runtime, assumptions, target, AMD64ConvertSnippets.class);
-            f2i = snippet("f2i", float.class, int.class);
-            f2l = snippet("f2l", float.class, long.class);
-            d2i = snippet("d2i", double.class, int.class);
-            d2l = snippet("d2l", double.class, long.class);
-        }
-
-        public void lower(ConvertNode convert, LoweringTool tool) {
-            if (convert.opcode == Op.F2I) {
-                lower0(convert, tool, f2i);
-            } else if (convert.opcode == Op.F2L) {
-                lower0(convert, tool, f2l);
-            } else if (convert.opcode == Op.D2I) {
-                lower0(convert, tool, d2i);
-            } else if (convert.opcode == Op.D2L) {
-                lower0(convert, tool, d2l);
-            }
-        }
-
-        private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) {
-            StructuredGraph graph = (StructuredGraph) convert.graph();
-
-            // Insert a unique placeholder node in place of the Convert node so that the
-            // Convert node can be used as an input to the snippet. All usage of the
-            // Convert node are replaced by the placeholder which in turn is replaced by the
-            // snippet.
-
-            LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp()));
-            convert.replaceAtUsages(replacee);
-            Key key = new Key(snippet);
-            Arguments arguments = arguments("input", convert.value()).add("result", convert);
-            SnippetTemplate template = cache.get(key, assumptions);
-            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments);
-            template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments);
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Mar 15 21:18:47 2013 +0100
@@ -47,13 +47,13 @@
     }
 
     @Override
-    public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) {
+    public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
         // SPARC: Create assembler.
         return null;
     }
 
     @Override
-    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir) {
+    public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIRGenerator lirGen) {
         // SPARC: Emit code
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Mar 15 21:18:47 2013 +0100
@@ -827,7 +827,7 @@
     /**
      * Gets the kind of array elements for the array type code that appears in a
      * {@link Bytecodes#NEWARRAY} bytecode.
-     *
+     * 
      * @param code the array type code
      * @return the kind from the array type code
      */
@@ -964,7 +964,7 @@
 
     private void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) {
         assert receiver != null;
-        if (!GraalOptions.AllowExplicitExceptionChecks || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE)) {
+        if (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE) {
             return;
         }
 
@@ -1224,7 +1224,7 @@
 
     /**
      * Helper function that sums up the probabilities of all keys that lead to a specific successor.
-     *
+     * 
      * @return an array of size successorCount with the accumulated probability for each successor.
      */
     private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Code.java	Fri Mar 15 21:18:33 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, 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.lir.amd64;
-
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.asm.*;
-
-/**
- * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
- */
-public abstract class AMD64Code implements LIR.Code {
-
-    @Override
-    public final void emitCode(TargetMethodAssembler tasm) {
-        emitCode(tasm, (AMD64MacroAssembler) tasm.asm);
-    }
-
-    public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm);
-}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri Mar 15 21:18:47 2013 +0100
@@ -63,16 +63,14 @@
     public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp {
         protected ConditionFlag condition;
         protected LabelRef destination;
-        @State protected LIRFrameState state;
 
-        public BranchOp(Condition condition, LabelRef destination, LIRFrameState info) {
-            this(intCond(condition), destination, info);
+        public BranchOp(Condition condition, LabelRef destination) {
+            this(intCond(condition), destination);
         }
 
-        public BranchOp(ConditionFlag condition, LabelRef destination, LIRFrameState state) {
+        public BranchOp(ConditionFlag condition, LabelRef destination) {
             this.condition = condition;
             this.destination = destination;
-            this.state = state;
         }
 
         @Override
@@ -96,8 +94,8 @@
     public static class FloatBranchOp extends BranchOp {
         protected boolean unorderedIsTrue;
 
-        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRFrameState info) {
-            super(floatCond(condition), destination, info);
+        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination) {
+            super(floatCond(condition), destination);
             this.unorderedIsTrue = unorderedIsTrue;
         }
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCode.java	Fri Mar 15 21:18:33 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * 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.ptx;
-
-import com.oracle.graal.asm.ptx.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.asm.*;
-
-/**
- * Convenience class to provide PTXAssembler for the {@link #emitCode} method.
- */
-public abstract class PTXCode implements LIR.Code {
-
-    @Override
-    public final void emitCode(TargetMethodAssembler tasm) {
-        emitCode(tasm, (PTXAssembler) tasm.asm);
-    }
-
-    public abstract void emitCode(TargetMethodAssembler tasm, PTXAssembler masm);
-}
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Fri Mar 15 21:18:47 2013 +0100
@@ -54,12 +54,10 @@
 
         protected Condition condition;
         protected LabelRef destination;
-        @State protected LIRFrameState state;
 
-        public BranchOp(Condition condition, LabelRef destination, LIRFrameState state) {
+        public BranchOp(Condition condition, LabelRef destination) {
             this.condition = condition;
             this.destination = destination;
-            this.state = state;
         }
 
         @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Fri Mar 15 21:18:47 2013 +0100
@@ -70,17 +70,11 @@
  * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size of such
  * a block may be greater than the size of a normal spill slot or the word size.
  * <p>
- * A runtime has two ways to reserve space in the stack frame for its own use:
- * <ul>
- * <li>A memory block somewhere in the frame of size
- * {@link CodeCacheProvider#getCustomStackAreaSize()}. The offset to this block is returned in
- * {@link CompilationResult#getCustomStackAreaOffset()}.
- * <li>At the beginning of the overflow argument area: The calling convention can specify that the
- * first overflow stack argument is not at offset 0, but at a specified offset o. Use
- * {@link CodeCacheProvider#getMinimumOutgoingSize()} to make sure that call-free methods also have
- * this space reserved. Then the VM can use memory the memory at offset 0 relative to the stack
- * pointer.
- * </ul>
+ * A runtime can reserve space at the beginning of the overflow argument area. The calling
+ * convention can specify that the first overflow stack argument is not at offset 0, but at a
+ * specified offset. Use {@link CodeCacheProvider#getMinimumOutgoingSize()} to make sure that
+ * call-free methods also have this space reserved. Then the VM can use the memory at offset 0
+ * relative to the stack pointer.
  */
 public final class FrameMap {
 
@@ -89,14 +83,9 @@
     public final RegisterConfig registerConfig;
 
     /**
-     * The initial frame size, not including the size of the return address. This is the constant
-     * space reserved by the runtime for all compiled methods.
-     */
-    public final int initialFrameSize;
-
-    /**
-     * The final frame size, not including the size of the return address. The value is only set
-     * after register allocation is complete, i.e., after all spill slots have been allocated.
+     * The final frame size, not including the size of the
+     * {@link Architecture#getReturnAddressSize() return address slot}. The value is only set after
+     * register allocation is complete, i.e., after all spill slots have been allocated.
      */
     private int frameSize;
 
@@ -117,12 +106,6 @@
     private final List<StackSlot> objectStackBlocks;
 
     /**
-     * The stack area reserved for use by the VM, or {@code null} if the VM does not request stack
-     * space.
-     */
-    private final StackSlot customArea;
-
-    /**
      * Records whether an offset to an incoming stack argument was ever returned by
      * {@link #offsetForStackSlot(StackSlot)}.
      */
@@ -139,8 +122,6 @@
         this.spillSize = returnAddressSize() + calleeSaveAreaSize();
         this.outgoingSize = runtime.getMinimumOutgoingSize();
         this.objectStackBlocks = new ArrayList<>();
-        this.customArea = allocateStackBlock(runtime.getCustomStackAreaSize(), false);
-        this.initialFrameSize = currentFrameSize();
     }
 
     private int returnAddressSize() {
@@ -161,7 +142,8 @@
     }
 
     /**
-     * Gets the frame size of the compiled frame, not including the size of the return address.
+     * Gets the frame size of the compiled frame, not including the size of the
+     * {@link Architecture#getReturnAddressSize() return address slot}.
      * 
      * @return The size of the frame (in bytes).
      */
@@ -171,7 +153,17 @@
     }
 
     /**
-     * Gets the total frame size of the compiled frame, including the size of the return address.
+     * Determines if any space is used in the frame apart from the
+     * {@link Architecture#getReturnAddressSize() return address slot}.
+     */
+    public boolean frameNeedsAllocating() {
+        int unalignedFrameSize = outgoingSize + spillSize - returnAddressSize();
+        return unalignedFrameSize != 0;
+    }
+
+    /**
+     * Gets the total frame size of the compiled frame, including the size of the
+     * {@link Architecture#getReturnAddressSize() return address slot}.
      * 
      * @return The total size of the frame (in bytes).
      */
@@ -194,6 +186,21 @@
      */
     public void finish() {
         assert this.frameSize == -1 : "must only be set once";
+        if (freedSlots != null) {
+            // If the freed slots cover the complete spill area (except for the return
+            // address slot), then the spill size is reset to its initial value.
+            // Without this, frameNeedsAllocating() would never return true.
+            int total = 0;
+            for (StackSlot s : freedSlots) {
+                total += target.sizeInBytes(s.getKind());
+            }
+            int initialSpillSize = returnAddressSize() + calleeSaveAreaSize();
+            if (total == spillSize - initialSpillSize) {
+                // reset spill area size
+                spillSize = initialSpillSize;
+            }
+            freedSlots = null;
+        }
         frameSize = currentFrameSize();
     }
 
@@ -223,16 +230,6 @@
     }
 
     /**
-     * Gets the offset of the stack area stack block reserved for use by the VM, or -1 if the VM
-     * does not request stack space.
-     * 
-     * @return The offset to the custom area (in bytes).
-     */
-    public int offsetToCustomArea() {
-        return customArea == null ? -1 : offsetForStackSlot(customArea);
-    }
-
-    /**
      * Informs the frame map that the compiled code calls a particular method, which may need stack
      * space for outgoing arguments.
      * 
@@ -265,11 +262,36 @@
      */
     public StackSlot allocateSpillSlot(Kind kind) {
         assert frameSize == -1 : "frame size must not yet be fixed";
+        if (freedSlots != null) {
+            for (Iterator<StackSlot> iter = freedSlots.iterator(); iter.hasNext();) {
+                StackSlot s = iter.next();
+                if (s.getKind() == kind) {
+                    iter.remove();
+                    if (freedSlots.isEmpty()) {
+                        freedSlots = null;
+                    }
+                    return s;
+                }
+            }
+        }
         int size = target.sizeInBytes(kind);
         spillSize = NumUtil.roundUp(spillSize + size, size);
         return getSlot(kind, 0);
     }
 
+    private List<StackSlot> freedSlots;
+
+    /**
+     * Frees a spill slot that was obtained via {@link #allocateSpillSlot(Kind)} such that it can be
+     * reused for the next allocation request for the same kind of slot.
+     */
+    public void freeSpillSlot(StackSlot slot) {
+        if (freedSlots == null) {
+            freedSlots = new ArrayList<>();
+        }
+        freedSlots.add(slot);
+    }
+
     /**
      * Reserves a block of memory in the frame of the method being compiled. The returned block is
      * aligned on a word boundary. If the requested size is 0, the method returns {@code null}.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Fri Mar 15 21:18:47 2013 +0100
@@ -56,12 +56,6 @@
      */
     private final List<Block> codeEmittingOrder;
 
-    /**
-     * Various out-of-line stubs to be emitted near the end of the method after all other LIR code
-     * has been emitted.
-     */
-    public final List<Code> stubs;
-
     private int numVariables;
 
     public SpillMoveFactory spillMoveFactory;
@@ -78,19 +72,6 @@
     private final SpeculationLog speculationLog;
 
     /**
-     * An opaque chunk of machine code.
-     */
-    public interface Code {
-
-        void emitCode(TargetMethodAssembler tasm);
-
-        /**
-         * A description of this code stub useful for commenting the code in a disassembly.
-         */
-        String description();
-    }
-
-    /**
      * Creates a new LIR instance for the specified compilation.
      */
     public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder, SpeculationLog speculationLog) {
@@ -99,8 +80,6 @@
         this.codeEmittingOrder = codeEmittingOrder;
         this.linearScanOrder = linearScanOrder;
         this.lirInstructions = new BlockMap<>(cfg);
-
-        stubs = new ArrayList<>();
         this.speculationLog = speculationLog;
     }
 
@@ -116,7 +95,7 @@
     }
 
     /**
-     * Determines if any instruction in the LIR has any debug info associated with it.
+     * Determines if any instruction in the LIR has debug info associated with it.
      */
     public boolean hasDebugInfo() {
         for (Block b : linearScanOrder()) {
@@ -167,11 +146,6 @@
         for (Block b : codeEmittingOrder()) {
             emitBlock(tasm, b);
         }
-
-        // generate code stubs
-        for (Code c : stubs) {
-            emitCodeStub(tasm, c);
-        }
     }
 
     private void emitBlock(TargetMethodAssembler tasm, Block block) {
@@ -202,13 +176,6 @@
         }
     }
 
-    private static void emitCodeStub(TargetMethodAssembler tasm, Code code) {
-        if (Debug.isDumpEnabled()) {
-            tasm.blockComment(String.format("code stub: %s", code.description()));
-        }
-        code.emitCode(tasm);
-    }
-
     public void setHasArgInCallerFrame() {
         hasArgInCallerFrame = true;
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Mar 15 21:18:47 2013 +0100
@@ -80,11 +80,9 @@
     public static class JumpOp extends LIRInstruction {
 
         private final LabelRef destination;
-        @State protected LIRFrameState state;
 
-        public JumpOp(LabelRef destination, LIRFrameState state) {
+        public JumpOp(LabelRef destination) {
             this.destination = destination;
-            this.state = state;
         }
 
         @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Fri Mar 15 21:18:47 2013 +0100
@@ -60,12 +60,12 @@
 
     private List<ExceptionInfo> exceptionInfoList;
 
-    public TargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext) {
+    public TargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, CompilationResult compilationResult) {
         this.target = target;
         this.runtime = runtime;
         this.frameMap = frameMap;
         this.asm = asm;
-        this.compilationResult = new CompilationResult();
+        this.compilationResult = compilationResult;
         this.frameContext = frameContext;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Fri Mar 15 21:18:47 2013 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}")
-public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, LIRLowerable, Node.IterableNodeType, Negatable {
+public final class FixedGuardNode extends FixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, Negatable {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
@@ -79,11 +79,6 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.emitGuardCheck(condition, reason, action, negated);
-    }
-
-    @Override
     public void simplify(SimplifierTool tool) {
         if (condition instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java	Fri Mar 15 21:18:47 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.nodes.type.*;
 
 public abstract class FixedNode extends ValueNode {
@@ -32,6 +34,10 @@
         super(stamp);
     }
 
+    public FixedNode(Stamp stamp, List<ValueNode> dependencies) {
+        super(stamp, dependencies);
+    }
+
     public FixedNode(Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java	Fri Mar 15 21:18:47 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import java.util.*;
+
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -43,6 +45,10 @@
         super(stamp);
     }
 
+    public FixedWithNextNode(Stamp stamp, List<ValueNode> dependencies) {
+        super(stamp, dependencies);
+    }
+
     public FixedWithNextNode(Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Fri Mar 15 21:18:47 2013 +0100
@@ -42,7 +42,7 @@
  * control flow would have reached the guarded node (without taking exceptions into account).
  */
 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}")
-public final class GuardNode extends FloatingNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, Negatable {
+public final class GuardNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, Negatable {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
@@ -91,11 +91,6 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool gen) {
-        gen.emitGuardCheck(condition(), reason(), action(), negated());
-    }
-
-    @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Fri Mar 15 21:18:47 2013 +0100
@@ -28,7 +28,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.type.GenericStamp.*;
 import com.oracle.graal.nodes.util.*;
 
 /**
@@ -174,9 +173,6 @@
 
     @Override
     public boolean verify() {
-        for (ValueNode v : dependencies().nonNull()) {
-            assertTrue(!(v.stamp() instanceof GenericStamp) || ((GenericStamp) v.stamp()).type() == GenericStampType.Dependency, "cannot depend on node with stamp %s", v.stamp());
-        }
         assertTrue(kind() != null, "Should have a valid kind");
         assertTrue(kind() == kind().getStackKind(), "Should have a stack kind : %s", kind());
         return super.verify();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java	Fri Mar 15 21:18:47 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import java.util.*;
+
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
@@ -58,6 +60,12 @@
         this.location = location;
     }
 
+    public AccessNode(ValueNode object, ValueNode location, Stamp stamp, List<ValueNode> dependencies) {
+        super(stamp, dependencies);
+        this.object = object;
+        this.location = location;
+    }
+
     public AccessNode(ValueNode object, ValueNode location, Stamp stamp, ValueNode... dependencies) {
         super(stamp, dependencies);
         this.object = object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Mar 15 21:18:47 2013 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -37,6 +39,10 @@
         super(object, location, stamp);
     }
 
+    public ReadNode(ValueNode object, ValueNode location, Stamp stamp, List<ValueNode> dependencies) {
+        super(object, location, stamp, dependencies);
+    }
+
     private ReadNode(ValueNode object, int displacement, Object locationIdentity, Kind kind) {
         super(object, object.graph().add(new LocationNode(locationIdentity, kind, displacement)), StampFactory.forKind(kind));
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Fri Mar 15 21:18:47 2013 +0100
@@ -64,7 +64,7 @@
                 return previousAnchor;
             }
         }
-        for (Node node : dependencies().nonNull().and(isNotA(BeginNode.class))) {
+        for (Node node : dependencies().nonNull().and(isNotA(FixedNode.class))) {
             if (node instanceof ConstantNode) {
                 continue;
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Mar 15 21:18:47 2013 +0100
@@ -97,8 +97,6 @@
 
     public abstract void emitMembar(int barriers);
 
-    public abstract void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason);
-
     public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason);
 
     public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args);
@@ -107,8 +105,6 @@
 
     public abstract void emitConditional(ConditionalNode i);
 
-    public abstract void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction deoptAction, boolean negated);
-
     public abstract void emitSwitch(SwitchNode i);
 
     public abstract void emitInvoke(Invoke i);
@@ -134,4 +130,10 @@
     public abstract void visitBreakpointNode(BreakpointNode i);
 
     public abstract void emitUnwind(Value operand);
+
+    /**
+     * Called just before register allocation is performed on the LIR owned by this generator.
+     */
+    public void beforeRegisterAllocation() {
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Fri Mar 15 21:18:47 2013 +0100
@@ -23,30 +23,47 @@
 package com.oracle.graal.phases.common;
 
 import java.util.*;
+import java.util.Map.Entry;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.schedule.*;
 
 public class GuardLoweringPhase extends Phase {
 
+    private TargetDescription target;
+
+    public GuardLoweringPhase(TargetDescription target) {
+        this.target = target;
+    }
+
     @Override
     protected void run(StructuredGraph graph) {
         SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
 
         for (Block block : schedule.getCFG().getBlocks()) {
-            processBlock(block, schedule, graph);
+            processBlock(block, schedule, graph, target);
         }
     }
 
-    private static void processBlock(Block block, SchedulePhase schedule, StructuredGraph graph) {
+    private static void processBlock(Block block, SchedulePhase schedule, StructuredGraph graph, TargetDescription target) {
         List<ScheduledNode> nodes = schedule.nodesFor(block);
+        if (GraalOptions.OptImplicitNullChecks && target.implicitNullCheckLimit > 0) {
+            useImplicitNullChecks(block.getBeginNode(), nodes, graph, target);
+        }
         FixedWithNextNode lastFixed = block.getBeginNode();
         BeginNode lastFastPath = null;
         for (Node node : nodes) {
+            if (!node.isAlive()) {
+                continue;
+            }
             if (lastFastPath != null && node instanceof FixedNode) {
                 lastFastPath.setNext((FixedNode) node);
                 lastFastPath = null;
@@ -81,4 +98,70 @@
             }
         }
     }
+
+    private static void useImplicitNullChecks(BeginNode begin, List<ScheduledNode> nodes, StructuredGraph graph, TargetDescription target) {
+        ListIterator<ScheduledNode> iterator = nodes.listIterator();
+        IdentityHashMap<ValueNode, GuardNode> nullGuarded = new IdentityHashMap<>();
+        FixedWithNextNode lastFixed = begin;
+        FixedWithNextNode reconnect = null;
+        while (iterator.hasNext()) {
+            Node node = iterator.next();
+
+            if (reconnect != null && node instanceof FixedNode) {
+                reconnect.setNext((FixedNode) node);
+                reconnect = null;
+            }
+            if (node instanceof FixedWithNextNode) {
+                lastFixed = (FixedWithNextNode) node;
+            }
+
+            if (node instanceof GuardNode) {
+                GuardNode guard = (GuardNode) node;
+                if (guard.negated() && guard.condition() instanceof IsNullNode) {
+                    ValueNode obj = ((IsNullNode) guard.condition()).object();
+                    nullGuarded.put(obj, guard);
+                }
+            } else if (node instanceof Access) {
+                Access access = (Access) node;
+                GuardNode guard = nullGuarded.get(access.object());
+                if (guard != null && isImplicitNullCheck(access.location(), target)) {
+                    NodeInputList<ValueNode> dependencies = ((ValueNode) access).dependencies();
+                    dependencies.remove(guard);
+                    if (access instanceof FloatingReadNode) {
+                        ReadNode read = graph.add(new ReadNode(access.object(), access.location(), ((FloatingReadNode) access).stamp(), dependencies));
+                        node.replaceAndDelete(read);
+                        access = read;
+                        lastFixed.setNext(read);
+                        lastFixed = read;
+                        reconnect = read;
+                        iterator.set(read);
+                    }
+                    assert access instanceof AccessNode;
+                    access.setNullCheck(true);
+                    LogicNode condition = guard.condition();
+                    guard.replaceAndDelete(access.node());
+                    if (condition.usages().isEmpty()) {
+                        GraphUtil.killWithUnusedFloatingInputs(condition);
+                    }
+                    nullGuarded.remove(access.object());
+                }
+            }
+            if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
+                nullGuarded.clear();
+            } else {
+                Iterator<Entry<ValueNode, GuardNode>> it = nullGuarded.entrySet().iterator();
+                while (it.hasNext()) {
+                    Entry<ValueNode, GuardNode> entry = it.next();
+                    GuardNode guard = entry.getValue();
+                    if (guard.usages().contains(node)) {
+                        it.remove();
+                    }
+                }
+            }
+        }
+    }
+
+    private static boolean isImplicitNullCheck(LocationNode location, TargetDescription target) {
+        return !(location instanceof IndexedLocationNode) && location.displacement() < target.implicitNullCheckLimit;
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Fri Mar 15 21:18:47 2013 +0100
@@ -83,7 +83,7 @@
         public ValueNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
             if (GraalOptions.OptEliminateGuards) {
                 for (Node usage : condition.usages()) {
-                    if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).negated() == negated && ((GuardNode) usage).dependencies().contains(guardAnchor)) {
+                    if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage) && ((GuardNode) usage).negated() == negated) {
                         return (GuardNode) usage;
                     }
                 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Fri Mar 15 21:18:47 2013 +0100
@@ -157,7 +157,7 @@
     public static boolean UseProfilingInformation            = true;
            static boolean RemoveNeverExecutedCode            = true;
            static boolean UseExceptionProbability            = true;
-    public static boolean AllowExplicitExceptionChecks       = true;
+           static boolean UseExceptionProbabilityForOperations = true;
     public static boolean OmitHotExceptionStacktrace         = ____;
     public static boolean GenSafepoints                      = true;
     public static boolean GenLoopSafepoints                  = true;
@@ -167,7 +167,7 @@
     public static boolean GenAssertionCode                   = ____;
     public static boolean AlignCallsForPatching              = true;
     public static boolean ResolveClassBeforeStaticInvoke     = ____;
-    public static boolean CanOmitFrame                       = false;
+    public static boolean CanOmitFrame                       = true;
     public static int     SafepointPollOffset                = 256;
 
     public static boolean MemoryAwareScheduling              = true;
@@ -185,7 +185,7 @@
     public static boolean SupportJsrBytecodes                = true;
 
     public static boolean OptAssumptions                     = true;
-    public static boolean OptConvertDeoptsToGuards           = true;
+    public static boolean OptConvertDeoptsToGuards           = ____;
     public static boolean OptReadElimination                 = true;
     public static boolean OptCanonicalizer                   = true;
     public static boolean OptScheduleOutOfLoops              = true;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Fri Mar 15 21:18:33 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Fri Mar 15 21:18:47 2013 +0100
@@ -33,8 +33,8 @@
     public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class));
     private static final DebugMetric disabledOptimisticOptsMetric = Debug.metric("DisabledOptimisticOpts");
 
-    private static enum Optimization {
-        RemoveNeverExecutedCode, UseTypeCheckedInlining, UseTypeCheckHints, UseExceptionProbability
+    public static enum Optimization {
+        RemoveNeverExecutedCode, UseTypeCheckedInlining, UseTypeCheckHints, UseExceptionProbabilityForOperations, UseExceptionProbability
     }
 
     private final Set<Optimization> enabledOpts;
@@ -42,6 +42,7 @@
     public OptimisticOptimizations(ResolvedJavaMethod method) {
         this.enabledOpts = EnumSet.noneOf(Optimization.class);
 
+        enabledOpts.add(Optimization.UseExceptionProbabilityForOperations);
         addOptimization(method, DeoptimizationReason.UnreachedCode, Optimization.RemoveNeverExecutedCode);
         addOptimization(method, DeoptimizationReason.TypeCheckedInliningViolated, Optimization.UseTypeCheckedInlining);
         addOptimization(method, DeoptimizationReason.OptimizedTypeCheckViolated, Optimization.UseTypeCheckHints);
@@ -60,6 +61,22 @@
         }
     }
 
+    public OptimisticOptimizations remove(Optimization... optimizations) {
+        Set<Optimization> newOptimizations = EnumSet.copyOf(enabledOpts);
+        for (Optimization o : optimizations) {
+            newOptimizations.remove(o);
+        }
+        return new OptimisticOptimizations(newOptimizations);
+    }
+
+    public OptimisticOptimizations add(Optimization... optimizations) {
+        Set<Optimization> newOptimizations = EnumSet.copyOf(enabledOpts);
+        for (Optimization o : optimizations) {
+            newOptimizations.add(o);
+        }
+        return new OptimisticOptimizations(newOptimizations);
+    }
+
     private OptimisticOptimizations(Set<Optimization> enabledOpts) {
         this.enabledOpts = enabledOpts;
     }
@@ -92,6 +109,10 @@
         return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability);
     }
 
+    public boolean useExceptionProbabilityForOperations() {
+        return GraalOptions.UseExceptionProbabilityForOperations && enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations);
+    }
+
     public boolean lessOptimisticThan(OptimisticOptimizations other) {
         for (Optimization opt : Optimization.values()) {
             if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.amd64/src/com/oracle/graal/snippets/amd64/AMD64ConvertSnippets.java	Fri Mar 15 21:18:47 2013 +0100
@@ -0,0 +1,196 @@
+/*
+ * 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.snippets.amd64;
+
+import static com.oracle.graal.snippets.SnippetTemplate.*;
+import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
+import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.calc.ConvertNode.Op;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.snippets.*;
+import com.oracle.graal.snippets.Snippet.Parameter;
+import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates;
+import com.oracle.graal.snippets.SnippetTemplate.Arguments;
+import com.oracle.graal.snippets.SnippetTemplate.Key;
+
+/**
+ * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match
+ * the semantics of the JVM specification.
+ */
+public class AMD64ConvertSnippets implements SnippetsInterface {
+
+    /**
+     * Converts a float to an int.
+     * <p>
+     * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the
+     * conversion. If the float value is a NaN, infinity or if the result of the conversion is
+     * larger than {@link Integer#MAX_VALUE} then CVTTSS2SI returns {@link Integer#MIN_VALUE} and
+     * extra tests are required on the float value to return the correct int value.
+     * 
+     * @param input the float being converted
+     * @param result the result produced by the CVTTSS2SI instruction
+     */
+    @Snippet
+    public static int f2i(@Parameter("input") float input, @Parameter("result") int result) {
+        if (result == Integer.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
+            if (Float.isNaN(input)) {
+                // input is NaN -> return 0
+                return 0;
+            } else if (input > 0.0f) {
+                // input is > 0 -> return max int
+                return Integer.MAX_VALUE;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Converts a float to a long.
+     * <p>
+     * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the
+     * conversion. If the float value is a NaN or infinity then CVTTSS2SI returns
+     * {@link Long#MIN_VALUE} and extra tests are required on the float value to return the correct
+     * long value.
+     * 
+     * @param input the float being converted
+     * @param result the result produced by the CVTTSS2SI instruction
+     */
+    @Snippet
+    public static long f2l(@Parameter("input") float input, @Parameter("result") long result) {
+        if (result == Long.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
+            if (Float.isNaN(input)) {
+                // input is NaN -> return 0
+                return 0;
+            } else if (input > 0.0f) {
+                // input is > 0 -> return max int
+                return Long.MAX_VALUE;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Converts a double to an int.
+     * <p>
+     * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the
+     * conversion. If the double value is a NaN, infinity or if the result of the conversion is
+     * larger than {@link Integer#MAX_VALUE} then CVTTSD2SI returns {@link Integer#MIN_VALUE} and
+     * extra tests are required on the double value to return the correct int value.
+     * 
+     * @param input the double being converted
+     * @param result the result produced by the CVTTSS2SI instruction
+     */
+    @Snippet
+    public static int d2i(@Parameter("input") double input, @Parameter("result") int result) {
+        if (result == Integer.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
+            if (Double.isNaN(input)) {
+                // input is NaN -> return 0
+                return 0;
+            } else if (input > 0.0d) {
+                // input is positive -> return maxInt
+                return Integer.MAX_VALUE;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Converts a double to a long.
+     * <p>
+     * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the
+     * conversion. If the double value is a NaN, infinity or if the result of the conversion is
+     * larger than {@link Long#MAX_VALUE} then CVTTSD2SI returns {@link Long#MIN_VALUE} and extra
+     * tests are required on the double value to return the correct long value.
+     * 
+     * @param input the double being converted
+     * @param result the result produced by the CVTTSS2SI instruction
+     */
+    @Snippet
+    public static long d2l(@Parameter("input") double input, @Parameter("result") long result) {
+        if (result == Long.MIN_VALUE) {
+            probability(NOT_FREQUENT_PROBABILITY);
+            if (Double.isNaN(input)) {
+                // input is NaN -> return 0
+                return 0;
+            } else if (input > 0.0d) {
+                // input is positive -> return maxInt
+                return Long.MAX_VALUE;
+            }
+        }
+        return result;
+    }
+
+    public static class Templates extends AbstractTemplates<AMD64ConvertSnippets> {
+
+        private final ResolvedJavaMethod f2i;
+        private final ResolvedJavaMethod f2l;
+        private final ResolvedJavaMethod d2i;
+        private final ResolvedJavaMethod d2l;
+
+        public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) {
+            super(runtime, assumptions, target, AMD64ConvertSnippets.class);
+            f2i = snippet("f2i", float.class, int.class);
+            f2l = snippet("f2l", float.class, long.class);
+            d2i = snippet("d2i", double.class, int.class);
+            d2l = snippet("d2l", double.class, long.class);
+        }
+
+        public void lower(ConvertNode convert, LoweringTool tool) {
+            if (convert.opcode == Op.F2I) {
+                lower0(convert, tool, f2i);
+            } else if (convert.opcode == Op.F2L) {
+                lower0(convert, tool, f2l);
+            } else if (convert.opcode == Op.D2I) {
+                lower0(convert, tool, d2i);
+            } else if (convert.opcode == Op.D2L) {
+                lower0(convert, tool, d2l);
+            }
+        }
+
+        private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) {
+            StructuredGraph graph = (StructuredGraph) convert.graph();
+
+            // Insert a unique placeholder node in place of the Convert node so that the
+            // Convert node can be used as an input to the snippet. All usage of the
+            // Convert node are replaced by the placeholder which in turn is replaced by the
+            // snippet.
+
+            LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp()));
+            convert.replaceAtUsages(replacee);
+            Key key = new Key(snippet);
+            Arguments arguments = arguments("input", convert.value()).add("result", convert);
+            SnippetTemplate template = cache.get(key, assumptions);
+            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments);
+            template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments);
+        }
+    }
+}
--- a/make/build-graal.xml	Fri Mar 15 21:18:33 2013 +0100
+++ b/make/build-graal.xml	Fri Mar 15 21:18:47 2013 +0100
@@ -23,33 +23,54 @@
  or visit www.oracle.com if you need additional information or have any
  questions.
 -->
-
-<project name="graal" basedir="." default="main">
-  <property name="src.dir"     value="${gamma.dir}/graal"/>
+<project basedir="." default="main" name="graal">
+  <property name="src.dir" value="${gamma.dir}/graal"/>
   <property name="classes.dir" value="${shared.dir}/graal"/>
-  <property name="jar.dir"     value="${shared.dir}"/>
-  <property name="jar.file"    value="${jar.dir}/graal.jar"/>
-
-  <target name="main" depends="jar"/>
-
+  <property name="jar.dir" value="${shared.dir}"/>
+  <property name="jar.file" value="${jar.dir}/graal.jar"/>
+  <target depends="jar" name="main"/>
   <target name="compile">
     <mkdir dir="${classes.dir}"/>
-    <javac srcdir="${src.dir}" destdir="${classes.dir}" debug="on" includeantruntime="false">
-      <include name="com.oracle.graal.*/**"/>
-      <exclude name="com.oracle.graal.test/**"/>
-      <exclude name="com.oracle.graal.*.test/**"/>
-      <exclude name="com.oracle.graal.jtt/**"/>
+    <javac debug="on" destdir="${classes.dir}" includeantruntime="false">
+      <src path="${src.dir}/com.oracle.graal.api.meta"/>
+      <src path="${src.dir}/com.oracle.graal.api.code"/>
+      <src path="${src.dir}/com.oracle.graal.graph"/>
+      <src path="${src.dir}/com.oracle.graal.debug"/>
+      <src path="${src.dir}/com.oracle.graal.nodes"/>
+      <src path="${src.dir}/com.oracle.graal.phases"/>
+      <src path="${src.dir}/com.oracle.graal.phases.common"/>
+      <src path="${src.dir}/com.oracle.graal.virtual"/>
+      <src path="${src.dir}/com.oracle.graal.loop"/>
+      <src path="${src.dir}/com.oracle.graal.alloc"/>
+      <src path="${src.dir}/com.oracle.graal.asm"/>
+      <src path="${src.dir}/com.oracle.graal.lir"/>
+      <src path="${src.dir}/com.oracle.graal.compiler"/>
+      <src path="${src.dir}/com.oracle.graal.bytecode"/>
+      <src path="${src.dir}/com.oracle.graal.java"/>
+      <src path="${src.dir}/com.oracle.graal.word"/>
+      <src path="${src.dir}/com.oracle.graal.snippets"/>
+      <src path="${src.dir}/com.oracle.graal.api.runtime"/>
+      <src path="${src.dir}/com.oracle.graal.printer"/>
+      <src path="${src.dir}/com.oracle.graal.hotspot"/>
+      <src path="${src.dir}/com.oracle.graal.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.asm.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.lir.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.compiler.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.hotspot.amd64"/>
+      <src path="${src.dir}/com.oracle.graal.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.asm.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.lir.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.compiler.sparc"/>
+      <src path="${src.dir}/com.oracle.graal.hotspot.sparc"/>
       <compilerarg value="-XDignore.symbol.file"/>
     </javac>
   </target>
-
-  <target name="jar" depends="compile">
+  <target depends="compile" name="jar">
     <mkdir dir="${jar.dir}"/>
-    <jar destfile="${jar.file}" basedir="${classes.dir}"/>
+    <jar basedir="${classes.dir}" destfile="${jar.file}"/>
   </target>
-
   <target name="clean">
     <delete dir="${classes.dir}"/>
-    <delete file="${jar.file}"/>
+    <delete file="${jar.filr}"/>
   </target>
 </project>
--- a/make/windows/makefiles/projectcreator.make	Fri Mar 15 21:18:33 2013 +0100
+++ b/make/windows/makefiles/projectcreator.make	Fri Mar 15 21:18:47 2013 +0100
@@ -176,8 +176,9 @@
 ##################################################
 ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
  -define_compiler1 COMPILER1 \
+ -define_compiler1 GRAAL \
  -ignorePath_compiler1 core \
- $(ProjectCreatorIDEOptionsIgnoreGraal:TARGET=compiler1) \
+ -ignorePath_compiler1 graal/generated \
  $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1)
 
 ##################################################
@@ -196,6 +197,7 @@
 ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
  -define_compiler2 COMPILER2 \
  -define_compiler2 GRAAL \
+ -define_compiler2 TIERED \
  -ignorePath_compiler2 core \
  -ignorePath_compiler2 graal/generated \
  -additionalFile_compiler2 $(Platform_arch_model).ad \
--- a/mx/commands.py	Fri Mar 15 21:18:33 2013 +0100
+++ b/mx/commands.py	Fri Mar 15 21:18:47 2013 +0100
@@ -52,31 +52,6 @@
 
 _make_eclipse_launch = False
 
-_copyrightTemplate = """/*
- * Copyright (c) {0}, 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.
- */
-
-"""
-
 _minVersion = mx.JavaVersion('1.7.0_04')
 
 def _chmodDir(chmodFlags, dirname, fnames):
@@ -462,6 +437,71 @@
     build = _vmbuild if _vmSourcesAvailable else 'product'
     print join(_graal_home, 'jdk' + str(mx.java().version), build)
 
+def initantbuild(args):
+    """(re)generates an ant build file for producing graal.jar"""
+    parser=ArgumentParser(prog='mx initantbuild')
+    parser.add_argument('-f', '--buildfile', help='file to generate', default=join(_graal_home, 'make', 'build-graal.xml'))
+
+    args = parser.parse_args(args)
+    
+    out = mx.XMLDoc()
+    
+    out.comment("""
+ 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.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ 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.
+""")
+    
+    out.open('project', {'name' : 'graal', 'default' : 'main', 'basedir' : '.'})
+    out.element('property', {'name' : 'src.dir', 'value' : '${gamma.dir}/graal'})
+    out.element('property', {'name' : 'classes.dir', 'value' : '${shared.dir}/graal'})
+    out.element('property', {'name' : 'jar.dir', 'value' : '${shared.dir}'})
+    out.element('property', {'name' : 'jar.file', 'value' : '${jar.dir}/graal.jar'})
+    
+    out.element('target', {'name' : 'main', 'depends' : 'jar'})
+
+    out.open('target', {'name' : 'compile'})
+    out.element('mkdir', {'dir' : '${classes.dir}'})
+    out.open('javac', {'destdir' : '${classes.dir}', 'debug' : 'on', 'includeantruntime' : 'false', })
+    for p in mx.sorted_deps(mx.distribution('GRAAL').deps):
+        out.element('src', {'path' : '${src.dir}/' + p.name})
+    out.element('compilerarg', {'value' : '-XDignore.symbol.file'})
+    out.close('javac')
+    out.close('target')
+
+    out.open('target', {'name' : 'jar', 'depends' : 'compile'})
+    out.element('mkdir', {'dir' : '${jar.dir}'})
+    out.element('jar', {'destfile' : '${jar.file}', 'basedir' : '${classes.dir}'})
+    out.close('target')
+    
+    out.open('target', {'name' : 'clean'})
+    out.element('delete', {'dir' : '${classes.dir}'})
+    out.element('delete', {'file' : '${jar.filr}'})
+    out.close('target')
+
+    out.close('project')
+    
+    mx.update_file(args.buildfile, out.xml(indent='  ', newl='\n'))
+
 def build(args, vm=None):
     """build the VM binary
 
@@ -490,6 +530,8 @@
     else:
         assert vm == 'graal', vm
         buildSuffix = 'graal'
+        
+    initantbuild([])
 
     for build in builds:
         if build == 'ide-build-target':
@@ -1132,6 +1174,7 @@
         'clean': [clean, ''],
         'hsdis': [hsdis, '[att]'],
         'hcfdis': [hcfdis, ''],
+        'initantbuild' : [initantbuild, '[-options]'],
         'igv' : [igv, ''],
         'jdkhome': [jdkhome, ''],
         'dacapo': [dacapo, '[[n] benchmark] [VM options|@DaCapo options]'],
--- a/mx/projects	Fri Mar 15 21:18:33 2013 +0100
+++ b/mx/projects	Fri Mar 15 21:18:47 2013 +0100
@@ -89,7 +89,7 @@
 # graal.hotspot.amd64
 project@com.oracle.graal.hotspot.amd64@subDir=graal
 project@com.oracle.graal.hotspot.amd64@sourceDirs=src
-project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.amd64
+project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.amd64,com.oracle.graal.snippets.amd64
 project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7
 
@@ -182,6 +182,13 @@
 project@com.oracle.graal.snippets@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.snippets@javaCompliance=1.7
 
+# graal.snippets.amd64
+project@com.oracle.graal.snippets.amd64@subDir=graal
+project@com.oracle.graal.snippets.amd64@sourceDirs=src
+project@com.oracle.graal.snippets.amd64@dependencies=com.oracle.graal.snippets
+project@com.oracle.graal.snippets.amd64@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.snippets.amd64@javaCompliance=1.7
+
 # graal.snippets.test
 project@com.oracle.graal.snippets.test@subDir=graal
 project@com.oracle.graal.snippets.test@sourceDirs=src
--- a/mxtool/mx.py	Fri Mar 15 21:18:33 2013 +0100
+++ b/mxtool/mx.py	Fri Mar 15 21:18:47 2013 +0100
@@ -630,6 +630,9 @@
         e.ownerDocument = self
         return e
 
+    def comment(self, txt):
+        self.current.appendChild(self.createComment(txt))
+
     def open(self, tag, attributes={}, data=None):
         element = self.createElement(tag)
         for key, value in attributes.items():