changeset 8380:2543392b9197

Merge.
author Roland Schatz <roland.schatz@oracle.com>
date Tue, 19 Mar 2013 17:01:39 +0100
parents fd9488c69250 40eaf9970bff
children 807fd844ed2a b4dea2fa8d9b
files graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64FrameOmissionTest.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/HotSpotAMD64LIRGenerator.java
diffstat 13 files changed, 413 insertions(+), 401 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64FrameOmissionTest.java	Tue Mar 19 15:46:37 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +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.amd64.test;
-
-import static com.oracle.graal.amd64.AMD64.*;
-
-import java.lang.reflect.*;
-
-import org.junit.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.phases.*;
-
-/**
- * Ensures that frame omission works in cases where it is expected to.
- */
-public class AMD64FrameOmissionTest extends GraalCompilerTest {
-
-    interface CodeGenerator {
-
-        void generateCode(AMD64Assembler asm);
-    }
-
-    public static void test1snippet() {
-        return;
-    }
-
-    @Test
-    public void test1() {
-        testHelper("test1snippet", new CodeGenerator() {
-
-            @Override
-            public void generateCode(AMD64Assembler asm) {
-                asm.ret(0);
-            }
-        });
-    }
-
-    public static int test2snippet(int x) {
-        return x + 5;
-    }
-
-    @Test
-    public void test2() {
-        testHelper("test2snippet", new CodeGenerator() {
-
-            @Override
-            public void generateCode(AMD64Assembler asm) {
-                asm.addl(rsi, 5);
-                asm.movl(rax, rsi);
-                asm.ret(0);
-            }
-        });
-    }
-
-    public static double test3snippet(double x) {
-        return 42.0D / x;
-    }
-
-    @Test
-    public void test3() {
-        testHelper("test3snippet", new CodeGenerator() {
-
-            @Override
-            public void generateCode(AMD64Assembler asm) {
-                asm.movsd(xmm1, new AMD64Address(rip, -40));
-                asm.divsd(xmm1, xmm0);
-                asm.movapd(xmm0, xmm1);
-                asm.ret(0);
-            }
-        });
-    }
-
-    private void testHelper(String name, CodeGenerator gen) {
-        Method method = getMethod(name);
-        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
-        InstalledCode installedCode = getCode(javaMethod, parse(method));
-
-        CodeCacheProvider codeCache = Graal.getRequiredCapability(CodeCacheProvider.class);
-        TargetDescription target = codeCache.getTarget();
-        RegisterConfig registerConfig = codeCache.lookupRegisterConfig();
-        AMD64Assembler asm = new AMD64Assembler(target, registerConfig);
-
-        gen.generateCode(asm);
-        for (int i = 0; i < GraalOptions.MethodEndBreakpointGuards; ++i) {
-            asm.int3();
-        }
-        while ((asm.codeBuffer.position() % 8) != 0) {
-            asm.hlt();
-        }
-
-        byte[] expectedCode = asm.codeBuffer.close(true);
-        byte[] actualCode = installedCode.getCode();
-
-        Assert.assertArrayEquals(expectedCode, actualCode);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java	Tue Mar 19 17:01:39 2013 +0100
@@ -0,0 +1,116 @@
+/*
+ * 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.test;
+
+import static com.oracle.graal.amd64.AMD64.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.compiler.test.*;
+
+/**
+ * Ensures that frame omission works in cases where it is expected to.
+ */
+public class AMD64HotSpotFrameOmissionTest extends GraalCompilerTest {
+
+    interface CodeGenerator {
+
+        void generateCode(AMD64Assembler asm);
+    }
+
+    public static void test1snippet() {
+        return;
+    }
+
+    @Test
+    public void test1() {
+        testHelper("test1snippet", new CodeGenerator() {
+
+            @Override
+            public void generateCode(AMD64Assembler asm) {
+                asm.ret(0);
+            }
+        });
+    }
+
+    public static int test2snippet(int x) {
+        return x + 5;
+    }
+
+    @Test
+    public void test2() {
+        testHelper("test2snippet", new CodeGenerator() {
+
+            @Override
+            public void generateCode(AMD64Assembler asm) {
+                asm.addl(rsi, 5);
+                asm.movl(rax, rsi);
+                asm.ret(0);
+            }
+        });
+    }
+
+    public static long test3snippet(long x) {
+        return 1 + x;
+    }
+
+    @Test
+    public void test3() {
+        testHelper("test3snippet", new CodeGenerator() {
+
+            @Override
+            public void generateCode(AMD64Assembler asm) {
+                asm.addq(rsi, 1);
+                asm.movq(rax, rsi);
+                asm.ret(0);
+            }
+        });
+    }
+
+    private void testHelper(String name, CodeGenerator gen) {
+        Method method = getMethod(name);
+        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        InstalledCode installedCode = getCode(javaMethod, parse(method));
+
+        CodeCacheProvider codeCache = Graal.getRequiredCapability(CodeCacheProvider.class);
+        TargetDescription target = codeCache.getTarget();
+        RegisterConfig registerConfig = codeCache.lookupRegisterConfig();
+        AMD64Assembler asm = new AMD64Assembler(target, registerConfig);
+
+        gen.generateCode(asm);
+        byte[] expectedCode = asm.codeBuffer.close(true);
+
+        // Only compare up to expectedCode.length bytes to ignore
+        // padding instructions adding during code installation
+        byte[] actualCode = Arrays.copyOf(installedCode.getCode(), expectedCode.length);
+
+        Assert.assertArrayEquals(expectedCode, actualCode);
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Mar 19 15:46:37 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Tue Mar 19 17:01:39 2013 +0100
@@ -64,7 +64,7 @@
 
     @Override
     public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) {
-        return new HotSpotAMD64LIRGenerator(graph, runtime(), target, frameMap, method, lir);
+        return new AMD64HotSpotLIRGenerator(graph, runtime(), target, frameMap, method, lir);
     }
 
     /**
@@ -141,7 +141,7 @@
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
         // - has no instructions with debug info
-        HotSpotAMD64LIRGenerator gen = (HotSpotAMD64LIRGenerator) lirGen;
+        AMD64HotSpotLIRGenerator gen = (AMD64HotSpotLIRGenerator) lirGen;
         FrameMap frameMap = gen.frameMap;
         LIR lir = gen.lir;
         boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame();
@@ -203,11 +203,5 @@
             asm.bind(unverifiedStub);
             AMD64Call.directJmp(tasm, asm, runtime().lookupRuntimeCall(IC_MISS_HANDLER));
         }
-
-        for (int i = 0; i < GraalOptions.MethodEndBreakpointGuards; ++i) {
-            asm.int3();
-        }
-
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Mar 19 17:01:39 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 AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSpotLIRGenerator {
+
+    private HotSpotRuntime runtime() {
+        return (HotSpotRuntime) runtime;
+    }
+
+    AMD64HotSpotLIRGenerator(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/HotSpotAMD64LIRGenerator.java	Tue Mar 19 15:46:37 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,255 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.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/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java	Tue Mar 19 15:46:37 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java	Tue Mar 19 17:01:39 2013 +0100
@@ -41,7 +41,7 @@
 /**
  * Substitutions for {@code com.sun.crypto.provider.AESCrypt} methods.
  */
-@ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt")
+@ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt", optional = true)
 public class AESCryptSubstitutions {
 
     static final long kOffset;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java	Tue Mar 19 15:46:37 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java	Tue Mar 19 17:01:39 2013 +0100
@@ -42,7 +42,7 @@
 /**
  * Substitutions for {@code com.sun.crypto.provider.CipherBlockChaining} methods.
  */
-@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining")
+@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining", optional = true)
 public class CipherBlockChainingSubstitutions {
 
     private static final long embeddedCipherOffset;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Mar 19 15:46:37 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Tue Mar 19 17:01:39 2013 +0100
@@ -105,7 +105,6 @@
     public static int     LoopUnswitchUncertaintyBoost       = 5;
 
     // debugging settings
-    public static int     MethodEndBreakpointGuards          = 2;
     public static boolean ZapStackOnMethodEntry              = ____;
     public static boolean DeoptALot                          = ____;
     public static boolean VerifyPhases                       = true;
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java	Tue Mar 19 15:46:37 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java	Tue Mar 19 17:01:39 2013 +0100
@@ -56,6 +56,12 @@
     String className() default "";
 
     /**
+     * Determines if the substitutions are for classes that may not be part of the runtime.
+     * Substitutions for such classes are omitted if the original classes cannot be found.
+     */
+    boolean optional() default false;
+
+    /**
      * Denotes a substitute method. A substitute method can call the original/substituted method by
      * making a recursive call to itself.
      */
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Tue Mar 19 15:46:37 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Tue Mar 19 17:01:39 2013 +0100
@@ -126,13 +126,17 @@
                 String originalName = originalName(substituteMethod, methodSubstitution.value());
                 Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic());
                 Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
-                installMethodSubstitution(originalMethod, substituteMethod);
+                if (originalMethod != null) {
+                    installMethodSubstitution(originalMethod, substituteMethod);
+                }
             }
             if (macroSubstitution != null) {
                 String originalName = originalName(substituteMethod, macroSubstitution.value());
                 Class[] originalParameters = originalParameters(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic());
                 Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
-                installMacroSubstitution(originalMethod, macroSubstitution.macro());
+                if (originalMethod != null) {
+                    installMacroSubstitution(originalMethod, macroSubstitution.macro());
+                }
             }
         }
     }
@@ -156,15 +160,10 @@
             original = runtime.lookupJavaConstructor((Constructor) originalMethod);
         }
         try {
-            Debug.log("inlinable substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
+            Debug.log("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
             StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute));
             Object oldValue = original.getCompilerStorage().put(Graph.class, graph);
             assert oldValue == null;
-
-            Debug.log("compilable substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
-            graph = makeGraph(substitute, inliningPolicy(substitute));
-            oldValue = original.getCompilerStorage().put(MethodSubstitution.class, graph);
-            assert oldValue == null;
         } finally {
             substitute = null;
             original = null;
@@ -333,13 +332,23 @@
         }
     }
 
-    private static Class resolveType(String className) {
+    /**
+     * Resolves a name to a class.
+     * 
+     * @param className the name of the class to resolve
+     * @param optional if true, resolution failure returns null
+     * @return the resolved class or null if resolution fails and {@code optional} is true
+     */
+    private static Class resolveType(String className, boolean optional) {
         try {
             // Need to use launcher class path to handle classes
             // that are not on the boot class path
             ClassLoader cl = Launcher.getLauncher().getClassLoader();
             return Class.forName(className, false, cl);
         } catch (ClassNotFoundException e) {
+            if (optional) {
+                return null;
+            }
             throw new GraalInternalError("Could not resolve type " + className);
         }
     }
@@ -352,7 +361,7 @@
             dimensions++;
         }
 
-        Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base));
+        Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base), false);
         return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass();
     }
 
@@ -377,7 +386,11 @@
     private static Member originalMethod(ClassSubstitution classSubstitution, String name, Class[] parameters) {
         Class<?> originalClass = classSubstitution.value();
         if (originalClass == ClassSubstitution.class) {
-            originalClass = resolveType(classSubstitution.className());
+            originalClass = resolveType(classSubstitution.className(), classSubstitution.optional());
+            if (originalClass == null) {
+                // optional class was not found
+                return null;
+            }
         }
         try {
             if (name.equals("<init>")) {
--- a/mx/projects	Tue Mar 19 15:46:37 2013 +0100
+++ b/mx/projects	Tue Mar 19 17:01:39 2013 +0100
@@ -114,6 +114,13 @@
 project@com.oracle.graal.hotspot.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.test@javaCompliance=1.7
 
+# graal.hotspot.amd64.test
+project@com.oracle.graal.hotspot.amd64.test@subDir=graal
+project@com.oracle.graal.hotspot.amd64.test@sourceDirs=src
+project@com.oracle.graal.hotspot.amd64.test@dependencies=com.oracle.graal.asm.amd64,com.oracle.graal.compiler.test
+project@com.oracle.graal.hotspot.amd64.test@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.7
+
 # graal.graph
 project@com.oracle.graal.graph@subDir=graal
 project@com.oracle.graal.graph@sourceDirs=src
@@ -248,7 +255,7 @@
 # graal.compiler.amd64.test
 project@com.oracle.graal.compiler.amd64.test@subDir=graal
 project@com.oracle.graal.compiler.amd64.test@sourceDirs=src
-project@com.oracle.graal.compiler.amd64.test@dependencies=com.oracle.graal.compiler.test,com.oracle.graal.asm.amd64
+project@com.oracle.graal.compiler.amd64.test@dependencies=com.oracle.graal.compiler.test
 project@com.oracle.graal.compiler.amd64.test@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.compiler.amd64.test@javaCompliance=1.7
 
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Tue Mar 19 15:46:37 2013 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Mar 19 17:01:39 2013 +0100
@@ -386,7 +386,6 @@
 
   // (very) conservative estimate: each site needs a constant section entry
   _constants_size = _sites->length() * (BytesPerLong*2);
-  _total_size = align_size_up(_code_size, HeapWordSize) + _constants_size;
 
   _next_call_type = MARK_INVOKE_INVALID;
 }
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Tue Mar 19 15:46:37 2013 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Tue Mar 19 17:01:39 2013 +0100
@@ -62,7 +62,6 @@
   jint          _custom_stack_area_offset;
   jint          _parameter_count;
   jint          _constants_size;
-  jint          _total_size;
 
   MarkId        _next_call_type;
   address       _invoke_mark_pc;