# HG changeset patch # User Thomas Wuerthinger # Date 1363712749 -3600 # Node ID b4dea2fa8d9b87797c7a259d491e5f0e8a9e36ff # Parent 496db8bf756d723eed479526cdfb80f1cd0cfdad# Parent 2543392b9197e5a6b26a6af05cc69ebeabe55d39 Merge. diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64FrameOmissionTest.java --- a/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64FrameOmissionTest.java Tue Mar 19 18:05:35 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); - } -} diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/AMD64HotSpotFrameOmissionTest.java --- /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 18:05:49 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); + } +} diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Mar 19 18:05:35 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Mar 19 18:05:49 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(); - } - } - } diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- /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 18:05:49 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 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); + } +} diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/HotSpotAMD64LIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/HotSpotAMD64LIRGenerator.java Tue Mar 19 18:05:35 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 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); - } -} diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java Tue Mar 19 18:05:35 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java Tue Mar 19 18:05:49 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; diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java Tue Mar 19 18:05:35 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java Tue Mar 19 18:05:49 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; diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Mar 19 18:05:35 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Mar 19 18:05:49 2013 +0100 @@ -1552,10 +1552,10 @@ private void createUnwind() { assert frameState.stackSize() == 1 : frameState; - synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI); ValueNode exception = frameState.apop(); FixedGuardNode guard = currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); append(guard); + synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI); UnwindNode unwindNode = currentGraph.add(new UnwindNode(exception)); append(unwindNode); } diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Mar 19 18:05:35 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Mar 19 18:05:49 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; diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java Tue Mar 19 18:05:35 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/ClassSubstitution.java Tue Mar 19 18:05:49 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. */ diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Mar 19 18:05:35 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Mar 19 18:05:49 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("")) { diff -r 496db8bf756d -r b4dea2fa8d9b graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Tue Mar 19 18:05:35 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Tue Mar 19 18:05:49 2013 +0100 @@ -357,20 +357,25 @@ graph.removeFixed(valueAnchorNode); } else if (checkCastUsage instanceof MethodCallTargetNode) { MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage; - assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod()) : "checkcast at " + sourceLocation(checkCastNode) + " not used by an unboxing method but by a call at " + - sourceLocation(checkCastCallTarget.usages().first()) + " to " + checkCastCallTarget.targetMethod(); - Invoke invokeNode = checkCastCallTarget.invoke(); - invokeNode.node().replaceAtUsages(newInstance); - if (invokeNode instanceof InvokeWithExceptionNode) { - // Destroy exception edge & clear stateAfter. - InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode; + if (pool.isUnboxingMethod(checkCastCallTarget.targetMethod())) { + Invoke invokeNode = checkCastCallTarget.invoke(); + invokeNode.node().replaceAtUsages(newInstance); + if (invokeNode instanceof InvokeWithExceptionNode) { + // Destroy exception edge & clear stateAfter. + InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode; - invokeWithExceptionNode.killExceptionEdge(); - graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next()); + invokeWithExceptionNode.killExceptionEdge(); + graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next()); + } else { + graph.removeFixed((InvokeNode) invokeNode); + } + checkCastCallTarget.safeDelete(); } else { - graph.removeFixed((InvokeNode) invokeNode); + assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(checkCastNode) + + " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " + + checkCastCallTarget.targetMethod(); + checkCastUsage.replaceFirstInput(checkCastNode, checkCastNode.object()); } - checkCastCallTarget.safeDelete(); } else if (checkCastUsage instanceof FrameState) { checkCastUsage.replaceFirstInput(checkCastNode, null); } else if (checkCastUsage instanceof ReturnNode && checkCastNode.object().stamp() == StampFactory.forNodeIntrinsic()) { diff -r 496db8bf756d -r b4dea2fa8d9b mx/projects --- a/mx/projects Tue Mar 19 18:05:35 2013 +0100 +++ b/mx/projects Tue Mar 19 18:05:49 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 diff -r 496db8bf756d -r b4dea2fa8d9b src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Tue Mar 19 18:05:35 2013 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Tue Mar 19 18:05:49 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; } diff -r 496db8bf756d -r b4dea2fa8d9b src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Tue Mar 19 18:05:35 2013 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Tue Mar 19 18:05:49 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;