# HG changeset patch # User Doug Simon # Date 1334238903 -7200 # Node ID efbb1e33e2f3d6f87c4c023d5a8181676c5b05b8 # Parent c005ca9437904c5525669e91dd762db1f8c6c99f removed XIR prologue and epilogues - architecture and runtime specific subclass of Backend is now used instead removed XIR ops: Align, StackOverflowCheck, PushFrame, PopFrame, RawBytes enhanced disassembly to annotate marks diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Apr 12 15:55:03 2012 +0200 @@ -41,7 +41,6 @@ import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; -import com.oracle.max.asm.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.*; @@ -269,18 +268,9 @@ return frameMap; } - private TargetMethodAssembler createAssembler(FrameMap frameMap, LIR lir) { - AbstractAssembler masm = backend.newAssembler(frameMap.registerConfig); - TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime, frameMap, lir.slowPaths, masm); - tasm.setFrameSize(frameMap.frameSize()); - tasm.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); - return tasm; - } - public CiTargetMethod emitCode(CiAssumptions assumptions, RiResolvedMethod method, LIR lir, FrameMap frameMap) { - TargetMethodAssembler tasm = createAssembler(frameMap, lir); - lir.emitCode(tasm); - + TargetMethodAssembler tasm = backend.newAssembler(frameMap, lir); + backend.emitCode(tasm, method, lir); CiTargetMethod targetMethod = tasm.finishTargetMethod(method, false); if (assumptions != null && !assumptions.isEmpty()) { targetMethod.setAssumptions(assumptions); diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Thu Apr 12 15:55:03 2012 +0200 @@ -493,11 +493,6 @@ } append(new ParametersOp(params)); - XirSnippet prologue = xir.genPrologue(null, method); - if (prologue != null) { - emitXir(prologue, null, null, false); - } - for (LocalNode local : graph.getNodes(LocalNode.class)) { CiValue param = params[local.index()]; assert param.kind == local.kind().stackKind(); @@ -603,11 +598,7 @@ operand = resultOperandFor(x.kind()); emitMove(operand(x.result()), operand); } - XirSnippet epilogue = xir.genEpilogue(site(x), method); - if (epilogue != null) { - emitXir(epilogue, x, null, false); - emitReturn(operand); - } + emitReturn(operand); } protected abstract void emitReturn(CiValue input); diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Thu Apr 12 15:55:03 2012 +0200 @@ -24,18 +24,26 @@ import java.lang.reflect.*; -import com.oracle.max.asm.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; /** * The {@code Backend} class represents a compiler backend for Graal. */ public abstract class Backend { + + /** + * The name of the system property whose value (if non-null) specifies the fully qualified + * name of the class to be instantiated by {@link #create(RiRuntime, CiTarget)}. + */ + public static final String BACKEND_CLASS_PROPERTY = "graal.compiler.backend.class"; + public final RiRuntime runtime; public final CiTarget target; @@ -44,8 +52,13 @@ this.target = target; } - public static Backend create(CiArchitecture arch, RiRuntime runtime, CiTarget target) { - String className = arch.getClass().getName().replace("com.oracle.max.asm", "com.oracle.graal.compiler") + "Backend"; + /** + * Creates the architecture and runtime specific back-end object. + * The class of the object instantiated must be in the {@link #BACKEND_CLASS_PROPERTY} system property. + */ + public static Backend create(RiRuntime runtime, CiTarget target) { + String className = System.getProperty(BACKEND_CLASS_PROPERTY); + assert className != null : "System property must be defined: " + BACKEND_CLASS_PROPERTY; try { Class c = Class.forName(className); Constructor cons = c.getDeclaredConstructor(RiRuntime.class, CiTarget.class); @@ -55,9 +68,46 @@ } } - public abstract FrameMap newFrameMap(RiRegisterConfig registerConfig); + public FrameMap newFrameMap(RiRegisterConfig registerConfig) { + return new FrameMap(runtime, target, registerConfig); + } + public abstract LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, RiResolvedMethod method, LIR lir, RiXirGenerator xir); - public abstract AbstractAssembler newAssembler(RiRegisterConfig registerConfig); + + public abstract TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir); + public abstract CiXirAssembler newXirAssembler(); + /** + * Emits code to do stack overflow checking. + * + * @param afterFrameInit specifies if the stack pointer has already been adjusted to allocate the current frame + */ + protected static void emitStackOverflowCheck(TargetMethodAssembler tasm, LIR lir, boolean afterFrameInit) { + if (GraalOptions.StackShadowPages > 0) { + int frameSize = tasm.frameMap.frameSize(); + if (frameSize > 0 || lir.containsCalls()) { + int lastFramePage = frameSize / tasm.target.pageSize; + // emit multiple stack bangs for methods with frames larger than a page + for (int i = 0; i <= lastFramePage; i++) { + int disp = (i + GraalOptions.StackShadowPages) * tasm.target.pageSize; + if (afterFrameInit) { + disp -= frameSize; + } + tasm.asm.bangStack(disp); + } + } + } + } + + /** + * 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 the method associated with {@code lir} + * @param lir the LIR of {@code method} + */ + public abstract void emitCode(TargetMethodAssembler tasm, RiResolvedMethod method, LIR lir); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64Backend.java Thu Apr 12 14:20:51 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2009, 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.target.amd64; - -import com.oracle.max.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.xir.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; - -/** - * The {@code X86Backend} class represents the backend for the AMD64 architecture. - */ -public class AMD64Backend extends Backend { - - public AMD64Backend(RiRuntime runtime, CiTarget target) { - super(runtime, target); - } - /** - * Creates a new LIRGenerator for x86. - * @param compilation the compilation for which to create the LIR generator - * @return an appropriate LIR generator instance - */ - @Override - public LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, RiResolvedMethod method, LIR lir, RiXirGenerator xir) { - return new AMD64LIRGenerator(graph, runtime, target, frameMap, method, lir, xir); - } - - @Override - public FrameMap newFrameMap(RiRegisterConfig registerConfig) { - return new FrameMap(runtime, target, registerConfig); - } - - @Override - public AbstractAssembler newAssembler(RiRegisterConfig registerConfig) { - return new AMD64MacroAssembler(target, registerConfig); - } - - @Override - public CiXirAssembler newXirAssembler() { - return new AMD64XirAssembler(target); - } -} diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java Thu Apr 12 15:55:03 2012 +0200 @@ -33,7 +33,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; -public class AMD64DeoptimizationStub extends AMD64SlowPath { +public class AMD64DeoptimizationStub extends AMD64Code { public final Label label = new Label(); public final LIRDebugInfo info; public final RiDeoptAction action; diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Thu Apr 12 15:55:03 2012 +0200 @@ -97,7 +97,6 @@ public AMD64LIRGenerator(Graph graph, RiRuntime runtime, CiTarget target, FrameMap frameMap, RiResolvedMethod method, LIR lir, RiXirGenerator xir) { super(graph, runtime, target, frameMap, method, lir, xir); - lir.methodEndMarker = new AMD64MethodEndStub(); lir.spillMoveFactory = new AMD64SpillMoveFactory(); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64MethodEndStub.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64MethodEndStub.java Thu Apr 12 14:20:51 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +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.target.amd64; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; - -public class AMD64MethodEndStub extends AMD64SlowPath { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - for (int i = 0; i < GraalOptions.MethodEndBreakpointGuards; ++i) { - masm.int3(); - } - } -} diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirAssembler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirAssembler.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirAssembler.java Thu Apr 12 15:55:03 2012 +0200 @@ -188,15 +188,10 @@ boundLabels.add(label); break; case Safepoint: - case Align: - case StackOverflowCheck: - case PushFrame: - case PopFrame: case Push: case Pop: case Mark: case Nop: - case RawBytes: case ShouldNotReachHere: break; default: diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java Thu Apr 12 15:55:03 2012 +0200 @@ -28,6 +28,10 @@ import java.util.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; import com.oracle.max.asm.*; import com.oracle.max.asm.target.amd64.*; import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; @@ -38,11 +42,6 @@ import com.oracle.max.cri.xir.CiXirAssembler.XirInstruction; import com.oracle.max.cri.xir.CiXirAssembler.XirLabel; import com.oracle.max.cri.xir.CiXirAssembler.XirMark; -import com.oracle.graal.compiler.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; public class AMD64XirOp extends LIRXirInstruction { public AMD64XirOp(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex, @@ -86,7 +85,7 @@ } } - private class SlowPath extends AMD64SlowPath { + private class SlowPath extends AMD64Code { public final Label[] labels; public SlowPath(Label[] labels) { @@ -391,52 +390,6 @@ masm.nullCheck(asRegister(pointer)); break; } - case Align: { - masm.align((Integer) inst.extra); - break; - } - case StackOverflowCheck: { - int frameSize = tasm.frameMap.frameSize(); - int lastFramePage = frameSize / tasm.target.pageSize; - // emit multiple stack bangs for methods with frames larger than a page - for (int i = 0; i <= lastFramePage; i++) { - int offset = (i + GraalOptions.StackShadowPages) * tasm.target.pageSize; - // Deduct 'frameSize' to handle frames larger than the shadow - bangStackWithOffset(tasm, masm, offset - frameSize); - } - break; - } - case PushFrame: { - int frameSize = tasm.frameMap.frameSize(); - masm.decrementq(AMD64.rsp, frameSize); // does not emit code for frameSize == 0 - if (GraalOptions.ZapStackOnMethodEntry) { - final int intSize = 4; - for (int i = 0; i < frameSize / intSize; ++i) { - masm.movl(new CiAddress(CiKind.Int, AMD64.rsp.asValue(), i * intSize), 0xC1C1C1C1); - } - } - CiCalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout(); - if (csl != null && csl.size != 0) { - int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea(); - assert frameToCSA >= 0; - masm.save(csl, frameToCSA); - } - break; - } - case PopFrame: { - int frameSize = tasm.frameMap.frameSize(); - - CiCalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout(); - if (csl != null && csl.size != 0) { - tasm.targetMethod.setRegisterRestoreEpilogueOffset(masm.codeBuffer.position()); - // saved all registers, restore all registers - int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea(); - masm.restore(csl, frameToCSA); - } - - masm.incrementq(AMD64.rsp, frameSize); - break; - } case Push: { CiRegisterValue value = assureInRegister(tasm, masm, operands[inst.x().index]); masm.push(asRegister(value)); @@ -470,12 +423,6 @@ } break; } - case RawBytes: { - for (byte b : (byte[]) inst.extra) { - masm.codeBuffer.emitByte(b & 0xff); - } - break; - } case ShouldNotReachHere: { AMD64Call.shouldNotReachHere(tasm, masm); break; @@ -521,16 +468,6 @@ masm.jcc(cflag, label); } - /** - * @param offset the offset RSP at which to bang. Note that this offset is relative to RSP after RSP has been - * adjusted to allocated the frame for the method. It denotes an offset "down" the stack. - * For very large frames, this means that the offset may actually be negative (i.e. denoting - * a slot "up" the stack above RSP). - */ - private static void bangStackWithOffset(TargetMethodAssembler tasm, AMD64MacroAssembler masm, int offset) { - masm.movq(new CiAddress(tasm.target.wordKind, AMD64.RSP, -offset), AMD64.rax); - } - private static CiValue assureNot64BitConstant(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue value) { if (isConstant(value) && (value.kind == CiKind.Long || value.kind == CiKind.Object)) { CiRegisterValue register = tasm.frameMap.registerConfig.getScratchRegister().asValue(value.kind); diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.examples/src/examples/HelloWorld.java --- a/graal/com.oracle.graal.examples/src/examples/HelloWorld.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.examples/src/examples/HelloWorld.java Thu Apr 12 15:55:03 2012 +0200 @@ -25,6 +25,20 @@ public class HelloWorld { public static void main(String[] args) { - System.out.println("hello world!"); + new HelloWorld(args).greet(); + } + + public HelloWorld(String[] args) { + name = args.length == 0 ? "world" : args[0]; + } + + public String name; + + public String getName() { + return name; + } + + public void greet() { + System.out.println("hello " + getName() + "!"); } } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerImpl.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerImpl.java Thu Apr 12 15:55:03 2012 +0200 @@ -175,7 +175,7 @@ generator = LoggingProxy.getProxy(RiXirGenerator.class, generator); } - Backend backend = Backend.create(target.arch, runtime, target); + Backend backend = Backend.create(runtime, target); generator.initialize(backend.newXirAssembler()); compiler = new GraalCompiler(getRuntime(), getTarget(), backend, generator); diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Apr 12 15:55:03 2012 +0200 @@ -147,7 +147,7 @@ /** * This method is the first method compiled during bootstrapping. Put any code in there that warms up compiler paths - * that are otherwise no exercised during bootstrapping and lead to later deoptimization when application code is + * that are otherwise not exercised during bootstrapping and lead to later deoptimization when application code is * compiled. */ @SuppressWarnings("unused") diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRegisterConfig.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRegisterConfig.java Thu Apr 12 15:55:03 2012 +0200 @@ -66,14 +66,7 @@ private final CiRegister[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7}; private final CiRegister[] allParameterRegisters; - private final CiRegister[] rsaRegs = { - rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, - r8, r9, r10, r11, r12, r13, r14, r15, - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - - private final CiCalleeSaveLayout registerSaveArea; + private final CiCalleeSaveLayout csl; public HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) { if (config.windowsOs) { @@ -83,9 +76,20 @@ } if (globalStubConfig) { - registerSaveArea = new CiCalleeSaveLayout(0, -1, 8, rsaRegs); + CiRegister[] regs = { + rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, + r8, r9, r10, r11, r12, r13, r14, r15, + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + csl = new CiCalleeSaveLayout(0, -1, 8, regs); } else { - registerSaveArea = new CiCalleeSaveLayout(0, 8, 8, new CiRegister[0]); + // 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 CiRegister[] regs = {}; + csl = new CiCalleeSaveLayout(0, size, 8, regs); } attributesMap = RiRegisterAttributes.createMap(this, AMD64.allRegisters); @@ -191,7 +195,7 @@ } public CiCalleeSaveLayout getCalleeSaveLayout() { - return registerSaveArea; + return csl; } @Override diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Thu Apr 12 15:55:03 2012 +0200 @@ -30,11 +30,13 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.cri.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.Compiler; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.target.amd64.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -42,9 +44,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiTargetMethod.Call; -import com.oracle.max.cri.ci.CiTargetMethod.DataPatch; -import com.oracle.max.cri.ci.CiTargetMethod.Safepoint; +import com.oracle.max.cri.ci.CiTargetMethod.*; import com.oracle.max.cri.ci.CiUtil.RefMapFormatter; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.ri.RiType.Representation; @@ -54,7 +54,7 @@ * CRI runtime implementation for the HotSpot VM. */ public class HotSpotRuntime implements GraalRuntime { - final HotSpotVMConfig config; + public final HotSpotVMConfig config; final HotSpotRegisterConfig regConfig; private final HotSpotRegisterConfig globalStubRegConfig; private final Compiler compiler; @@ -64,6 +64,8 @@ this.compiler = compiler; regConfig = new HotSpotRegisterConfig(config, false); globalStubRegConfig = new HotSpotRegisterConfig(config, true); + + System.setProperty(Backend.BACKEND_CLASS_PROPERTY, HotSpotAMD64Backend.class.getName()); } @Override @@ -81,20 +83,42 @@ return compiler.getVMEntries().disassembleNative(code, address); } - private String getTargetName(Object target) { + /** + * Decodes a call target to a mnemonic if possible. + */ + private String getTargetName(Call call) { Field[] fields = config.getClass().getDeclaredFields(); for (Field f : fields) { if (f.getName().endsWith("Stub")) { f.setAccessible(true); try { - if (f.get(config) == target) { + if (f.get(config).equals(call.target)) { return f.getName(); } } catch (Exception e) { } } } - return String.valueOf(target); + return String.valueOf(call.target); + } + + /** + * Decodes a mark to a mnemonic if possible. + */ + private static String getMarkName(Mark mark) { + Field[] fields = HotSpotXirGenerator.class.getDeclaredFields(); + for (Field f : fields) { + if (Modifier.isStatic(f.getModifiers()) && f.getName().startsWith("MARK_")) { + f.setAccessible(true); + try { + if (f.get(null).equals(mark.id)) { + return f.getName(); + } + } catch (Exception e) { + } + } + } + return "MARK:" + mark.id; } @Override @@ -112,7 +136,7 @@ if (call.debugInfo != null) { hcf.addComment(call.pcOffset + call.size, CiUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString()); } - addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call.target) + "}"); + addOperandComment(hcf, call.pcOffset, "{" + getTargetName(call) + "}"); } else { if (safepoint.debugInfo != null) { hcf.addComment(safepoint.pcOffset, CiUtil.append(new StringBuilder(100), safepoint.debugInfo, slotFormatter).toString()); @@ -123,6 +147,9 @@ for (DataPatch site : tm.dataReferences) { hcf.addOperandComment(site.pcOffset, "{" + site.constant + "}"); } + for (Mark mark : tm.marks) { + hcf.addComment(mark.pcOffset, getMarkName(mark)); + } return hcf.toEmbeddedString(); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotXirGenerator.java Thu Apr 12 15:55:03 2012 +0200 @@ -23,10 +23,8 @@ package com.oracle.graal.hotspot.ri; import static com.oracle.graal.hotspot.ri.TemplateFlag.*; -import static com.oracle.max.cri.ci.CiCallingConvention.Type.*; import static com.oracle.max.cri.ci.CiValueUtil.*; -import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; @@ -49,25 +47,25 @@ // this needs to correspond to graal_CodeInstaller.hpp // @formatter:off - private static final Integer MARK_VERIFIED_ENTRY = 0x0001; - private static final Integer MARK_UNVERIFIED_ENTRY = 0x0002; - private static final Integer MARK_OSR_ENTRY = 0x0003; - private static final Integer MARK_UNWIND_ENTRY = 0x0004; - private static final Integer MARK_EXCEPTION_HANDLER_ENTRY = 0x0005; - private static final Integer MARK_DEOPT_HANDLER_ENTRY = 0x0006; + public static final Integer MARK_VERIFIED_ENTRY = 0x0001; + public static final Integer MARK_UNVERIFIED_ENTRY = 0x0002; + public static final Integer MARK_OSR_ENTRY = 0x0003; + public static final Integer MARK_UNWIND_ENTRY = 0x0004; + public static final Integer MARK_EXCEPTION_HANDLER_ENTRY = 0x0005; + public static final Integer MARK_DEOPT_HANDLER_ENTRY = 0x0006; - private static final Integer MARK_STATIC_CALL_STUB = 0x1000; + public static final Integer MARK_STATIC_CALL_STUB = 0x1000; - private static final Integer MARK_INVOKEINTERFACE = 0x2001; - private static final Integer MARK_INVOKESTATIC = 0x2002; - private static final Integer MARK_INVOKESPECIAL = 0x2003; - private static final Integer MARK_INVOKEVIRTUAL = 0x2004; + public static final Integer MARK_INVOKEINTERFACE = 0x2001; + public static final Integer MARK_INVOKESTATIC = 0x2002; + public static final Integer MARK_INVOKESPECIAL = 0x2003; + public static final Integer MARK_INVOKEVIRTUAL = 0x2004; - private static final Integer MARK_IMPLICIT_NULL = 0x3000; - private static final Integer MARK_POLL_NEAR = 0x3001; - private static final Integer MARK_POLL_RETURN_NEAR = 0x3002; - private static final Integer MARK_POLL_FAR = 0x3003; - private static final Integer MARK_POLL_RETURN_FAR = 0x3004; + public static final Integer MARK_IMPLICIT_NULL = 0x3000; + public static final Integer MARK_POLL_NEAR = 0x3001; + public static final Integer MARK_POLL_RETURN_NEAR = 0x3002; + public static final Integer MARK_POLL_FAR = 0x3003; + public static final Integer MARK_POLL_RETURN_FAR = 0x3004; // @formatter:on @@ -104,98 +102,6 @@ } } - private SimpleTemplates prologueTemplates = new SimpleTemplates(STATIC_METHOD) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - XirOperand framePointer = asm.createRegisterTemp("frame pointer", target.wordKind, AMD64.rbp); - XirOperand stackPointer = asm.createRegisterTemp("stack pointer", target.wordKind, AMD64.rsp); - XirLabel unverifiedStub = null; - - asm.mark(MARK_OSR_ENTRY); - asm.mark(MARK_UNVERIFIED_ENTRY); - if (!is(STATIC_METHOD, flags)) { - unverifiedStub = asm.createOutOfLineLabel("unverified"); - - XirOperand temp = asm.createRegisterTemp("temp (r10)", target.wordKind, AMD64.r10); - XirOperand cache = asm.createRegisterTemp("cache (rax)", target.wordKind, AMD64.rax); - - CiCallingConvention conventions = registerConfig.getCallingConvention(JavaCallee, new CiKind[] {CiKind.Object}, target, false); - XirOperand receiver = asm.createRegister("receiver", target.wordKind, asRegister(conventions.locations[0])); - - asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), false); - asm.jneq(unverifiedStub, cache, temp); - } - asm.align(config.codeEntryAlignment); - asm.mark(MARK_VERIFIED_ENTRY); - asm.stackOverflowCheck(); - asm.push(framePointer); - asm.mov(framePointer, stackPointer); - // Compensate for the push of framePointer (the XIR instruction pushFrame is not flexible enough to reduce the frame size, wait until XIR goes away to fix this). - asm.add(stackPointer, stackPointer, asm.i(8)); - asm.pushFrame(); - - // -- out of line ------------------------------------------------------- - XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); - XirOperand exceptionOop = asm.createTemp("exception oop", CiKind.Object); - XirLabel unwind = asm.createOutOfLineLabel("unwind"); - asm.bindOutOfLine(unwind); - - asm.mark(MARK_UNWIND_ENTRY); - - asm.pload(CiKind.Object, exceptionOop, thread, asm.i(config.threadExceptionOopOffset), false); - asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.createConstant(CiConstant.NULL_OBJECT), false); - asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); - - asm.callRuntime(config.unwindExceptionStub, null, exceptionOop); - asm.shouldNotReachHere(); - - asm.mark(MARK_EXCEPTION_HANDLER_ENTRY); - asm.callRuntime(config.handleExceptionStub, null); - asm.shouldNotReachHere(); - - asm.mark(MARK_DEOPT_HANDLER_ENTRY); - asm.callRuntime(config.handleDeoptStub, null); - asm.shouldNotReachHere(); - - if (!is(STATIC_METHOD, flags)) { - asm.bindOutOfLine(unverifiedStub); - asm.jmpRuntime(config.inlineCacheMissStub); - } - - return asm.finishTemplate(is(STATIC_METHOD, flags) ? "static prologue" : "prologue"); - } - }; - - private SimpleTemplates epilogueTemplates = new SimpleTemplates(STATIC_METHOD, SYNCHRONIZED) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - XirOperand framePointer = asm.createRegisterTemp("frame pointer", target.wordKind, AMD64.rbp); - XirOperand stackPointer = asm.createRegisterTemp("stack pointer", target.wordKind, AMD64.rsp); - - asm.popFrame(); - asm.pload(CiKind.Long, framePointer, stackPointer, asm.i(-8), false); - - if (GraalOptions.GenSafepoints) { - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10); - if (config.isPollingPageFar) { - asm.mov(temp, wordConst(asm, config.safepointPollingAddress)); - asm.mark(MARK_POLL_RETURN_FAR); - asm.pload(target.wordKind, temp, temp, true); - } else { - XirOperand rip = asm.createRegister("rip", target.wordKind, AMD64.rip); - asm.mark(MARK_POLL_RETURN_NEAR); - asm.pload(target.wordKind, temp, rip, asm.i(0xEFBEADDE), true); - } - } - - return asm.finishTemplate("epilogue"); - } - }; - private SimpleTemplates safepointTemplates = new SimpleTemplates() { @Override @@ -958,17 +864,6 @@ }; @Override - public XirSnippet genPrologue(XirSite site, RiResolvedMethod method) { - boolean staticMethod = Modifier.isStatic(method.accessFlags()); - return new XirSnippet(staticMethod ? prologueTemplates.get(site, STATIC_METHOD) : prologueTemplates.get(site)); - } - - @Override - public XirSnippet genEpilogue(XirSite site, RiResolvedMethod method) { - return new XirSnippet(epilogueTemplates.get(site)); - } - - @Override public XirSnippet genSafepointPoll(XirSite site) { return new XirSnippet(safepointTemplates.get(site)); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java Thu Apr 12 15:55:03 2012 +0200 @@ -0,0 +1,215 @@ +/* + * 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.target.amd64; + +import static com.oracle.graal.hotspot.ri.HotSpotXirGenerator.*; +import static com.oracle.max.asm.target.amd64.AMD64.*; +import static com.oracle.max.cri.ci.CiCallingConvention.Type.*; +import static com.oracle.max.cri.ci.CiValueUtil.*; + +import java.lang.reflect.*; + +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.compiler.target.amd64.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.ri.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.*; +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.xir.*; + +public class HotSpotAMD64Backend extends Backend { + + public HotSpotAMD64Backend(RiRuntime runtime, CiTarget target) { + super(runtime, target); + } + + @Override + public LIRGenerator newLIRGenerator(Graph graph, FrameMap frameMap, RiResolvedMethod method, LIR lir, RiXirGenerator xir) { + return new AMD64LIRGenerator(graph, runtime, target, frameMap, method, lir, xir); + } + + @Override + public AMD64XirAssembler newXirAssembler() { + return new AMD64XirAssembler(target); + } + + class HotSpotFrameContext implements FrameContext { + + private final LIR lir; + private boolean needsLeave; + + public HotSpotFrameContext(LIR lir) { + this.lir = lir; + } + + @Override + public void enter(TargetMethodAssembler tasm) { + FrameMap frameMap = tasm.frameMap; + int frameSize = frameMap.frameSize(); + if (frameSize != 0) { + AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm; + emitStackOverflowCheck(tasm, lir, false); + asm.push(rbp); + asm.movq(rbp, rsp); + asm.decrementq(rsp, frameSize - 8); // account for the push of RBP above + if (GraalOptions.ZapStackOnMethodEntry) { + final int intSize = 4; + for (int i = 0; i < frameSize / intSize; ++i) { + asm.movl(new CiAddress(CiKind.Int, rsp.asValue(), i * intSize), 0xC1C1C1C1); + } + } + CiCalleeSaveLayout csl = frameMap.registerConfig.getCalleeSaveLayout(); + if (csl != null && csl.size != 0) { + int frameToCSA = frameMap.offsetToCalleeSaveArea(); + assert frameToCSA >= 0; + asm.save(csl, frameToCSA); + } + needsLeave = true; + } + } + + @Override + public void leave(TargetMethodAssembler tasm) { + if (!needsLeave) { + return; + } + + int frameSize = tasm.frameMap.frameSize(); + AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm; + CiCalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout(); + RiRegisterConfig regConfig = tasm.frameMap.registerConfig; + + if (csl != null && csl.size != 0) { + tasm.targetMethod.setRegisterRestoreEpilogueOffset(asm.codeBuffer.position()); + // saved all registers, restore all registers + int frameToCSA = tasm.frameMap.offsetToCalleeSaveArea(); + asm.restore(csl, frameToCSA); + } + + asm.incrementq(rsp, frameSize - 8); // account for the pop of RBP below + asm.pop(rbp); + + if (GraalOptions.GenSafepoints) { + HotSpotVMConfig config = ((HotSpotRuntime) runtime).config; + + // If at the return point, then the frame has already been popped + // so deoptimization cannot be performed here. The HotSpot runtime + // detects this case - see the definition of frame::should_be_deoptimized() + + CiRegister scratch = regConfig.getScratchRegister(); + if (config.isPollingPageFar) { + asm.movq(scratch, config.safepointPollingAddress); + tasm.recordMark(MARK_POLL_RETURN_FAR); + asm.movq(scratch, new CiAddress(tasm.target.wordKind, scratch.asValue())); + } else { + tasm.recordMark(MARK_POLL_RETURN_NEAR); + asm.movq(scratch, new CiAddress(tasm.target.wordKind, rip.asValue())); + } + } + } + } + + @Override + public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) { + AbstractAssembler masm = new AMD64MacroAssembler(target, frameMap.registerConfig); + HotSpotFrameContext frameContext = new HotSpotFrameContext(lir); + TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime, frameMap, masm, frameContext); + tasm.setFrameSize(frameMap.frameSize()); + tasm.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); + return tasm; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, RiResolvedMethod method, LIR lir) { + AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm; + FrameMap frameMap = tasm.frameMap; + RiRegisterConfig regConfig = frameMap.registerConfig; + HotSpotVMConfig config = ((HotSpotRuntime) runtime).config; + Label unverifiedStub = new Label(); + CiRegister scratch = regConfig.getScratchRegister(); + + // Emit the prefix + tasm.recordMark(MARK_OSR_ENTRY); + tasm.recordMark(MARK_UNVERIFIED_ENTRY); + + boolean isStatic = Modifier.isStatic(method.accessFlags()); + if (!isStatic) { + CiCallingConvention cc = regConfig.getCallingConvention(JavaCallee, new CiKind[] {CiKind.Object}, target, false); + CiRegister inlineCacheKlass = rax; // see definition of IC_Klass in c1_LIRAssembler_x86.cpp + CiRegister receiver = asRegister(cc.locations[0]); + CiAddress src = new CiAddress(target.wordKind, receiver.asValue(), config.hubOffset); + + asm.movq(scratch, src); + asm.cmpq(inlineCacheKlass, scratch); + asm.jcc(ConditionFlag.notEqual, unverifiedStub); + } + + asm.align(config.codeEntryAlignment); + tasm.recordMark(MARK_VERIFIED_ENTRY); + + // Emit code for the LIR + lir.emitCode(tasm); + + // Emit the suffix (i.e. out-of-line stubs) + CiRegister thread = r15; + CiRegister exceptionOop = regConfig.getScratchRegister(); + Label unwind = new Label(); + asm.bind(unwind); + tasm.recordMark(MARK_UNWIND_ENTRY); + CiAddress exceptionOopField = new CiAddress(CiKind.Object, thread.asValue(), config.threadExceptionOopOffset); + CiAddress exceptionPcField = new CiAddress(CiKind.Object, thread.asValue(), config.threadExceptionPcOffset); + asm.movq(exceptionOop, exceptionOopField); + asm.xorq(scratch, scratch); + asm.movq(exceptionOopField, scratch); + asm.movq(exceptionPcField, scratch); + + AMD64Call.directCall(tasm, asm, config.unwindExceptionStub, null); + AMD64Call.shouldNotReachHere(tasm, asm); + + tasm.recordMark(MARK_EXCEPTION_HANDLER_ENTRY); + AMD64Call.directCall(tasm, asm, config.handleExceptionStub, null); + AMD64Call.shouldNotReachHere(tasm, asm); + + tasm.recordMark(MARK_DEOPT_HANDLER_ENTRY); + AMD64Call.directCall(tasm, asm, config.handleDeoptStub, null); + AMD64Call.shouldNotReachHere(tasm, asm); + + if (!isStatic) { + asm.bind(unverifiedStub); + AMD64Call.directJmp(tasm, asm, config.inlineCacheMissStub); + } + + for (int i = 0; i < GraalOptions.MethodEndBreakpointGuards; ++i) { + asm.int3(); + } + } +} diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Thu Apr 12 15:55:03 2012 +0200 @@ -510,7 +510,7 @@ masm.bind(slowPath.continuation); } - private static class ConvertSlowPath extends AMD64SlowPath { + private static class ConvertSlowPath extends AMD64Code { public final Label start = new Label(); public final Label continuation = new Label(); private final CiValue result; diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Code.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Code.java Thu Apr 12 15:55:03 2012 +0200 @@ -0,0 +1,39 @@ +/* + * 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.max.asm.target.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); +} diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Thu Apr 12 15:55:03 2012 +0200 @@ -46,6 +46,7 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + tasm.frameContext.leave(tasm); masm.ret(0); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SlowPath.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SlowPath.java Thu Apr 12 14:20:51 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +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.max.asm.target.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 AMD64SlowPath implements LIR.SlowPath { - @Override - public final void emitCode(TargetMethodAssembler tasm) { - emitCode(tasm, (AMD64MacroAssembler) tasm.asm); - } - - public abstract void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm); -} diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Thu Apr 12 15:55:03 2012 +0200 @@ -55,14 +55,9 @@ private final List codeEmittingOrder; - public final List slowPaths; - - public final List deoptimizationStubs; + public final List slowPaths; - /** - * The last slow path emitted, which can be used emit marker bytes. - */ - public SlowPath methodEndMarker; + public final List deoptimizationStubs; private int numVariables; @@ -73,7 +68,10 @@ LIRInstruction createExchange(CiValue input1, CiValue input2); } - public interface SlowPath { + /** + * An opaque chunk of machine code. + */ + public interface Code { void emitCode(TargetMethodAssembler tasm); } @@ -97,6 +95,23 @@ } /** + * Determines if this LIR contains any calls. + */ + public boolean containsCalls() { + if (!slowPaths.isEmpty() || !deoptimizationStubs.isEmpty()) { + return true; + } + for (Block b : linearScanOrder) { + for (LIRInstruction op : b.lir) { + if (op.hasCall()) { + return true; + } + } + } + return false; + } + + /** * Gets the linear scan ordering of blocks as a list. * @return the blocks in linear scan order */ @@ -117,20 +132,23 @@ } public void emitCode(TargetMethodAssembler tasm) { + tasm.frameContext.enter(tasm); + for (Block b : codeEmittingOrder()) { emitBlock(tasm, b); } // generate code for slow cases - for (SlowPath sp : slowPaths) { + for (Code sp : slowPaths) { + emitSlowPath(tasm, sp); + } + for (Code sp : tasm.slowPaths) { emitSlowPath(tasm, sp); } // generate deoptimization stubs - for (SlowPath sp : deoptimizationStubs) { + for (Code sp : deoptimizationStubs) { emitSlowPath(tasm, sp); } - // generate traps at the end of the method - emitSlowPath(tasm, methodEndMarker); } private static void emitBlock(TargetMethodAssembler tasm, Block block) { @@ -161,7 +179,7 @@ } } - private static void emitSlowPath(TargetMethodAssembler tasm, SlowPath sp) { + private static void emitSlowPath(TargetMethodAssembler tasm, Code sp) { if (Debug.isDumpEnabled()) { tasm.blockComment(String.format("slow case %s", sp.getClass().getName())); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/FrameContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/FrameContext.java Thu Apr 12 15:55:03 2012 +0200 @@ -0,0 +1,50 @@ +/* + * 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.lir.asm; + + +/** + * Emits common code for {@linkplain #enter(TargetMethodAssembler) entering} and + * {@linkplain #leave(TargetMethodAssembler) leaving} a method. + */ +public interface FrameContext { + /** + * Emits code common to all entry points of a method. This may include: + *
    + *
  • setting up the stack frame
  • + *
  • saving callee-saved registers
  • + *
  • stack overflow checking
  • + *
+ */ + void enter(TargetMethodAssembler tasm); + + /** + * Emits code to be executed just prior to returning from a method. This may include: + *
    + *
  • restoring callee-saved registers
  • + *
  • performing a safepoint
  • + *
  • destroying the stack frame
  • + *
+ */ + void leave(TargetMethodAssembler tasm); +} diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Thu Apr 12 15:55:03 2012 +0200 @@ -51,18 +51,20 @@ public final CiTarget target; public final RiRuntime runtime; public final FrameMap frameMap; - public final List slowPaths; + public final List slowPaths; + public final FrameContext frameContext; private List exceptionInfoList; private int lastSafepointPos; - public TargetMethodAssembler(CiTarget target, RiRuntime runtime, FrameMap frameMap, List slowPaths, AbstractAssembler asm) { + public TargetMethodAssembler(CiTarget target, RiRuntime runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext) { this.target = target; this.runtime = runtime; this.frameMap = frameMap; - this.slowPaths = slowPaths; + this.slowPaths = new ArrayList<>(); this.asm = asm; this.targetMethod = new CiTargetMethod(); + this.frameContext = frameContext; // 0 is a valid pc for safepoints in template methods this.lastSafepointPos = -1; } @@ -71,6 +73,10 @@ targetMethod.setFrameSize(frameSize); } + public CiTargetMethod.Mark recordMark(Object id) { + return targetMethod.recordMark(asm.codeBuffer.position(), id, null); + } + public CiTargetMethod.Mark recordMark(Object id, CiTargetMethod.Mark[] references) { return targetMethod.recordMark(asm.codeBuffer.position(), id, references); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/GraalRuntime.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/GraalRuntime.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/cri/GraalRuntime.java Thu Apr 12 15:55:03 2012 +0200 @@ -24,10 +24,10 @@ import java.util.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; /** * Graal-specific extensions for the runtime interface that must be implemented by the VM. diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java --- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java Thu Apr 12 15:55:03 2012 +0200 @@ -54,6 +54,14 @@ protected abstract void patchJumpTarget(int branch, int jumpTarget); + /** + * Emits instruction(s) that access an address specified by a given displacement from the stack pointer + * in the direction that the stack grows (which is down on most architectures). + * + * @param disp the displacement from the stack pointer at which the stack should be accessed + */ + public abstract void bangStack(int disp); + protected final void emitByte(int x) { codeBuffer.emitByte(x); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java --- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java Thu Apr 12 15:55:03 2012 +0200 @@ -2985,4 +2985,9 @@ public void fstp(int i) { emitx87(0xDD, 0xD8, i); } + + @Override + public void bangStack(int disp) { + movq(new CiAddress(target.wordKind, AMD64.RSP, -disp), AMD64.rax); + } } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/CiXirAssembler.java Thu Apr 12 15:55:03 2012 +0200 @@ -553,26 +553,6 @@ */ Safepoint, /** - * Align the code following this instruction to a multiple of (int)extra. - */ - Align, - /** - * Creates the stack banging overflow check. - */ - StackOverflowCheck, - /** - * Creates the stack frame for the method and spills callee-save registers (if any) to the {@linkplain CiRegisterSaveArea register save area}. - */ - PushFrame, - /** - * Restores all callee-save registers (if any) and removes the stack frame of the method. - */ - PopFrame, - /** - * Inserts an array of bytes directly into the code output. - */ - RawBytes, - /** * Pushes a value onto the stack. */ Push, @@ -769,27 +749,6 @@ append(new XirInstruction(CiKind.Void, null, Safepoint, null)); } - public void align(int multiple) { - assert multiple > 0; - append(new XirInstruction(CiKind.Void, multiple, Align, null)); - } - - public void stackOverflowCheck() { - append(new XirInstruction(CiKind.Void, null, StackOverflowCheck, null)); - } - - public void pushFrame() { - append(new XirInstruction(CiKind.Void, null, PushFrame, null)); - } - - public void popFrame() { - append(new XirInstruction(CiKind.Void, null, PopFrame, null)); - } - - public void rawBytes(byte[] bytes) { - append(new XirInstruction(CiKind.Void, bytes, RawBytes, null)); - } - public void push(XirOperand value) { append(new XirInstruction(CiKind.Void, Push, VOID, value)); } diff -r c005ca943790 -r efbb1e33e2f3 graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Thu Apr 12 14:20:51 2012 +0200 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Thu Apr 12 15:55:03 2012 +0200 @@ -31,16 +31,6 @@ */ public interface RiXirGenerator { - /** - * Note: may return {@code null}. - */ - XirSnippet genPrologue(XirSite site, RiResolvedMethod method); - - /** - * Note: may return {@code null} in which case the compiler will not emit a return instruction. - */ - XirSnippet genEpilogue(XirSite site, RiResolvedMethod method); - XirSnippet genSafepointPoll(XirSite site); XirSnippet genExceptionObject(XirSite site);