# HG changeset patch # User Doug Simon # Date 1367353362 -7200 # Node ID 56c12e0c15c1f9c949a3cafbc45be9410f2bee02 # Parent c021bfc839e6bc10c253b5790e6c4e257859cf4f# Parent ca34e36c53e84ba209ee7072423c03d9d99149c8 Merge. diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Tue Apr 30 22:22:42 2013 +0200 @@ -115,5 +115,11 @@ Descriptor getDescriptor(); - boolean preservesRegisters(); + /** + * Determines if the target routine destroys all registers. + * + * @return {@code true} if the register allocator must save all live registers around a call to + * this target + */ + boolean destroysRegisters(); } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue Apr 30 22:22:42 2013 +0200 @@ -413,7 +413,7 @@ */ boolean hasCall(int opId) { assert isEven(opId) : "opId not even"; - return instructionForId(opId).hasCall(); + return instructionForId(opId).destroysCallerSavedRegisters(); } /** @@ -1181,7 +1181,7 @@ final int opId = op.id(); // add a temp range for each register if operation destroys caller-save registers - if (op.hasCall()) { + if (op.destroysCallerSavedRegisters()) { for (Register r : callerSaveRegs) { if (attributes(r).isAllocatable()) { addTemp(r.asValue(), opId, RegisterPriority.None, Kind.Illegal); @@ -1681,7 +1681,7 @@ // before we've consumed the inputs. if (op.id() < interval.currentTo()) { // caller-save registers must not be included into oop-maps at calls - assert !op.hasCall() || !isRegister(operand) || !isCallerSave(operand) : "interval is in a caller-save register at a call . register will be overwritten"; + assert !op.destroysCallerSavedRegisters() || !isRegister(operand) || !isCallerSave(operand) : "interval is in a caller-save register at a call . register will be overwritten"; frameMap.setReference(interval.location(), registerRefMap, frameRefMap); @@ -1703,7 +1703,7 @@ } private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRFrameState info) { - BitSet registerRefMap = op.hasCall() ? null : frameMap.initRegisterRefMap(); + BitSet registerRefMap = op.destroysCallerSavedRegisters() ? null : frameMap.initRegisterRefMap(); BitSet frameRefMap = frameMap.initFrameRefMap(); computeOopMap(iw, op, registerRefMap, frameRefMap); diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java Tue Apr 30 22:22:42 2013 +0200 @@ -248,7 +248,7 @@ // check if input operands are correct op.forEachInput(useProc); // invalidate all caller save registers at calls - if (op.hasCall()) { + if (op.destroysCallerSavedRegisters()) { for (Register r : allocator.frameMap.registerConfig.getCallerSaveRegisters()) { statePut(inputState, r.asValue(), null); } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Tue Apr 30 22:22:42 2013 +0200 @@ -22,23 +22,21 @@ */ package com.oracle.graal.hotspot.amd64; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @Opcode("DEOPT") final class AMD64DeoptimizeOp extends AMD64LIRInstruction { - public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class); - private DeoptimizationAction action; private DeoptimizationReason reason; @State private LIRFrameState info; @@ -54,6 +52,6 @@ HotSpotGraalRuntime runtime = graalRuntime(); Register thread = runtime.getRuntime().threadRegister(); masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason)); - AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE), null, false, info); + AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(UNCOMMON_TRAP), null, false, info); } } diff -r ca34e36c53e8 -r 56c12e0c15c1 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 Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Apr 30 22:22:42 2013 +0200 @@ -34,7 +34,6 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; @@ -45,8 +44,8 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; import com.oracle.graal.lir.StandardOp.ParametersOp; -import com.oracle.graal.lir.LIRInstruction.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; @@ -59,9 +58,6 @@ public class AMD64HotSpotBackend extends HotSpotBackend { private static final Unsafe unsafe = Unsafe.getUnsafe(); - public static final Descriptor EXCEPTION_HANDLER = new Descriptor("exceptionHandler", true, void.class); - public static final Descriptor DEOPT_HANDLER = new Descriptor("deoptHandler", true, void.class); - public static final Descriptor IC_MISS_HANDLER = new Descriptor("icMissHandler", true, void.class); public AMD64HotSpotBackend(HotSpotRuntime runtime, TargetDescription target) { super(runtime, target); @@ -100,13 +96,21 @@ class HotSpotFrameContext implements FrameContext { + final boolean isStub; + + HotSpotFrameContext(boolean isStub) { + this.isStub = isStub; + } + @Override public void enter(TargetMethodAssembler tasm) { FrameMap frameMap = tasm.frameMap; int frameSize = frameMap.frameSize(); AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm; - emitStackOverflowCheck(tasm, false); + if (!isStub) { + emitStackOverflowCheck(tasm, false); + } asm.decrementq(rsp, frameSize); if (GraalOptions.ZapStackOnMethodEntry) { final int intSize = 4; @@ -156,16 +160,16 @@ LIR lir = gen.lir; boolean omitFrame = CanOmitFrame && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame(); + Stub stub = runtime().asStub(lirGen.method()); AbstractAssembler masm = createAssembler(frameMap); - HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(); + HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(stub != null); TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult); tasm.setFrameSize(frameMap.frameSize()); StackSlot deoptimizationRescueSlot = gen.deoptimizationRescueSlot; - if (deoptimizationRescueSlot != null) { + if (deoptimizationRescueSlot != null && stub == null) { tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot)); } - Stub stub = runtime().asStub(lirGen.method()); if (stub != null) { final Set definedRegisters = gatherDefinedRegisters(lir); @@ -244,8 +248,8 @@ // Emit code for the LIR lirGen.lir.emitCode(tasm); - boolean frameOmitted = tasm.frameContext == null; - if (!frameOmitted) { + HotSpotFrameContext frameContext = (HotSpotFrameContext) tasm.frameContext; + if (frameContext != null && !frameContext.isStub) { tasm.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY); AMD64Call.directCall(tasm, asm, runtime().lookupRuntimeCall(EXCEPTION_HANDLER), null, false, null); tasm.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY); diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Tue Apr 30 22:22:42 2013 +0200 @@ -24,8 +24,8 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.amd64.AMD64DeoptimizeOp.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -66,6 +66,6 @@ HotSpotGraalRuntime runtime = graalRuntime(); Register thread = runtime.getRuntime().threadRegister(); masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason)); - AMD64Call.directJmp(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE)); + AMD64Call.directJmp(tasm, masm, tasm.runtime.lookupRuntimeCall(UNCOMMON_TRAP)); } } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Apr 30 22:22:42 2013 +0200 @@ -24,8 +24,6 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*; -import static com.oracle.graal.hotspot.amd64.AMD64DeoptimizeOp.*; -import static com.oracle.graal.hotspot.amd64.AMD64HotSpotBackend.*; import static com.oracle.graal.hotspot.amd64.AMD64HotSpotUnwindOp.*; import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*; @@ -62,10 +60,6 @@ /* ret */ ret(Kind.Void), /* arg0: exception */ rax.asValue(Kind.Object)); - addRuntimeCall(DEOPTIMIZE, config.deoptimizeStub, - /* temps */ null, - /* ret */ ret(Kind.Void)); - addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub, /* temps */ new Register[]{AMD64.rax}, /* ret */ ret(Kind.Float), @@ -148,18 +142,6 @@ /* arg2: key */ word, /* arg3: r */ word, /* arg4: inLength */ Kind.Int)); - - addRuntimeCall(EXCEPTION_HANDLER, config.handleExceptionStub, - /* temps */ null, - /* ret */ ret(Kind.Void)); - - addRuntimeCall(DEOPT_HANDLER, config.handleDeoptStub, - /* temps */ null, - /* ret */ ret(Kind.Void)); - - addRuntimeCall(IC_MISS_HANDLER, config.inlineCacheMissStub, - /* temps */ null, - /* ret */ ret(Kind.Void)); // @formatter:on } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Tue Apr 30 22:22:42 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; @@ -31,6 +32,26 @@ */ public abstract class HotSpotBackend extends Backend { + /** + * Descriptor for SharedRuntime::deopt_blob()->uncommon_trap(). + */ + public static final Descriptor UNCOMMON_TRAP = new Descriptor("deoptimize", true, void.class); + + /** + * Descriptor for GraalRuntime::handle_exception_nofpu_id. + */ + public static final Descriptor EXCEPTION_HANDLER = new Descriptor("exceptionHandler", true, void.class); + + /** + * Descriptor for SharedRuntime::deopt_blob()->unpack(). + */ + public static final Descriptor DEOPT_HANDLER = new Descriptor("deoptHandler", true, void.class); + + /** + * Descriptor for SharedRuntime::get_ic_miss_stub(). + */ + public static final Descriptor IC_MISS_HANDLER = new Descriptor("icMissHandler", true, void.class); + public HotSpotBackend(HotSpotRuntime runtime, TargetDescription target) { super(runtime, target); } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Tue Apr 30 22:22:42 2013 +0200 @@ -111,10 +111,24 @@ } } + public long getAddress() { + assert address != 0L : "address not yet finalized: " + this; + return address; + } + @Override - public boolean preservesRegisters() { - assert address != 0; - return true; + public boolean destroysRegisters() { + if (isCRuntimeCall) { + // Even though most native ABIs define some callee saved registers, + // for simplicity we force the register allocator to save all live + // registers across a C runtime call as such calls are only made from + // compiled stubs which a) are slow path and b) will typically only + // have very few live registers across a C runtime call + return true; + } + // This is a call to a compiled (or assembler) stub which saves + // all registers (apart from its temporaries) + return false; } /** diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Apr 30 22:22:42 2013 +0200 @@ -353,7 +353,7 @@ public long verifyOopStub; public long vmErrorStub; - public long deoptimizeStub; + public long uncommonTrapStub; public long unwindExceptionStub; public long osrMigrationEndStub; public long createNullPointerExceptionStub; @@ -368,7 +368,6 @@ public long logPrimitiveStub; public long logObjectStub; public long logPrintfStub; - public long stubPrintfStub; public int deoptReasonNone; public long identityHashCodeStub; public long aescryptEncryptBlockStub; @@ -381,6 +380,7 @@ public long newMultiArrayAddress; public long registerFinalizerAddress; public long threadIsInterruptedAddress; + public long stubPrintfAddress; public int deoptReasonNullCheck; public int deoptReasonRangeCheck; diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Apr 30 22:22:42 2013 +0200 @@ -28,6 +28,7 @@ import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.api.meta.Value.*; import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*; import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; @@ -215,6 +216,10 @@ /* ret */ ret(Kind.Void), /* arg0: long */ javaCallingConvention(Kind.Long)); + addRuntimeCall(UNCOMMON_TRAP, config.uncommonTrapStub, + /* temps */ null, + /* ret */ ret(Kind.Void)); + addStubCall(REGISTER_FINALIZER, /* ret */ ret(Kind.Void), /* arg0: object */ javaCallingConvention(Kind.Object)); @@ -304,13 +309,12 @@ /* arg2: value */ Kind.Long, /* arg3: value */ Kind.Long)); - addRuntimeCall(STUB_PRINTF, config.stubPrintfStub, - /* temps */ null, + addCRuntimeCall(STUB_PRINTF_C, config.stubPrintfAddress, /* ret */ ret(Kind.Void), - /* arg0: format */ javaCallingConvention(Kind.Long, - /* arg1: value */ Kind.Long, - /* arg2: value */ Kind.Long, - /* arg3: value */ Kind.Long)); + /* arg0: format */ nativeCallingConvention(Kind.Long, + /* arg1: value */ Kind.Long, + /* arg2: value */ Kind.Long, + /* arg3: value */ Kind.Long)); addRuntimeCall(LOG_OBJECT, config.logObjectStub, /* temps */ null, @@ -329,6 +333,17 @@ /* arg1: receiverThread */ Kind.Object, /* arg1: clearInterrupted */ Kind.Boolean)); + addRuntimeCall(EXCEPTION_HANDLER, config.handleExceptionStub, + /* temps */ null, + /* ret */ ret(Kind.Void)); + + addRuntimeCall(DEOPT_HANDLER, config.handleDeoptStub, + /* temps */ null, + /* ret */ ret(Kind.Void)); + + addRuntimeCall(IC_MISS_HANDLER, config.inlineCacheMissStub, + /* temps */ null, + /* ret */ ret(Kind.Void)); // @formatter:on } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Apr 30 22:22:42 2013 +0200 @@ -24,6 +24,8 @@ import static com.oracle.graal.api.code.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.api.meta.MetaUtil.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.nodes.CStringNode.*; import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; @@ -32,7 +34,9 @@ import java.util.concurrent.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.Call; import com.oracle.graal.api.code.CompilationResult.DataPatch; +import com.oracle.graal.api.code.CompilationResult.Infopoint; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; @@ -46,7 +50,6 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; @@ -61,7 +64,8 @@ /** * Base class for implementing some low level code providing the out-of-line slow path for a - * snippet. A concrete stub is defined a subclass of this class. + * snippet. A stub may make a direct call to a HotSpot C/C++ runtime function. Stubs are installed + * as an instance of the C++ RuntimeStub class (as opposed to nmethod). *

* Implementation detail: The stub classes re-use some of the functionality for {@link Snippet}s * purely for convenience (e.g., can re-use the {@link ReplacementsImpl}). @@ -130,11 +134,22 @@ return linkage; } - private boolean checkCompilationResult(CompilationResult compResult) { + /** + * Checks the conditions a compilation must satisfy to be installed as a RuntimeStub. + */ + private boolean checkStubInvariants(CompilationResult compResult) { for (DataPatch data : compResult.getDataReferences()) { Constant constant = data.constant; - assert constant.getKind() != Kind.Object : MetaUtil.format("%h.%n(%p): ", getMethod()) + "cannot have embedded oop: " + constant; - assert constant.getPrimitiveAnnotation() == null : MetaUtil.format("%h.%n(%p): ", getMethod()) + "cannot have embedded metadata: " + constant; + assert constant.getKind() != Kind.Object : format("%h.%n(%p): ", getMethod()) + "cannot have embedded oop: " + constant; + assert constant.getPrimitiveAnnotation() == null : format("%h.%n(%p): ", getMethod()) + "cannot have embedded metadata: " + constant; + } + for (Infopoint infopoint : compResult.getInfopoints()) { + assert infopoint instanceof Call : format("%h.%n(%p): ", getMethod()) + "cannot have non-call infopoint: " + infopoint; + Call call = (Call) infopoint; + assert call.target instanceof HotSpotRuntimeCallTarget : format("%h.%n(%p): ", getMethod()) + "cannot have non runtime call: " + call.target; + HotSpotRuntimeCallTarget callTarget = (HotSpotRuntimeCallTarget) call.target; + assert callTarget.getAddress() == graalRuntime().getConfig().uncommonTrapStub || callTarget.isCRuntimeCall() : format("%h.%n(%p): ", getMethod()) + + "must only call C runtime or deoptimization stub, not " + call.target; } return true; } @@ -181,7 +196,7 @@ final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog()); - assert checkCompilationResult(compResult); + assert checkStubInvariants(compResult); assert definedRegisters != null; code = Debug.scope("CodeInstall", new Callable() { @@ -238,27 +253,29 @@ } } - public static final Descriptor STUB_PRINTF = new Descriptor("stubPrintf", false, void.class, Word.class, long.class, long.class, long.class); + public static final Descriptor STUB_PRINTF_C = descriptorFor(Stub.class, "printfC", false); - @NodeIntrinsic(RuntimeCallNode.class) - private static native void printf(@ConstantNodeParameter Descriptor stubPrintf, Word format, long v1, long v2, long v3); + @NodeIntrinsic(CRuntimeCall.class) + private static native void printfC(@ConstantNodeParameter Descriptor stubPrintf, Word format, long v1, long v2, long v3); /** - * Prints a formatted string to the log stream. + * Prints a formatted string to the log stream. This differs from {@link Log#LOG_PRINTF} in that + * the format string is a C string in the C heap which avoids having an embedded oop in a + * RuntimeStub. * * @param format a C style printf format value that can contain at most one conversion specifier * (i.e., a sequence of characters starting with '%'). * @param value the value associated with the conversion specifier */ public static void printf(String format, long value) { - printf(STUB_PRINTF, cstring(format), value, 0L, 0L); + printfC(STUB_PRINTF_C, cstring(format), value, 0L, 0L); } public static void printf(String format, long v1, long v2) { - printf(STUB_PRINTF, cstring(format), v1, v2, 0L); + printfC(STUB_PRINTF_C, cstring(format), v1, v2, 0L); } public static void printf(String format, long v1, long v2, long v3) { - printf(STUB_PRINTF, cstring(format), v1, v2, v3); + printfC(STUB_PRINTF_C, cstring(format), v1, v2, v3); } } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Tue Apr 30 22:22:42 2013 +0200 @@ -51,7 +51,7 @@ } @Override - public boolean hasCall() { + public boolean destroysCallerSavedRegisters() { return true; } } @@ -112,8 +112,8 @@ } @Override - public boolean hasCall() { - return !callTarget.preservesRegisters(); + public boolean destroysCallerSavedRegisters() { + return callTarget.destroysRegisters(); } } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Tue Apr 30 22:22:42 2013 +0200 @@ -244,7 +244,7 @@ } public final boolean hasOperands() { - return instructionClass.hasOperands() || hasState() || hasCall(); + return instructionClass.hasOperands() || hasState() || destroysCallerSavedRegisters(); } public final boolean hasState() { @@ -252,10 +252,9 @@ } /** - * Returns true when this instruction is a call instruction that destroys all caller-saved - * registers. + * Determines if this instruction destroys all caller-saved registers.. */ - public boolean hasCall() { + public boolean destroysCallerSavedRegisters() { return false; } diff -r ca34e36c53e8 -r 56c12e0c15c1 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Tue Apr 30 21:38:48 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Tue Apr 30 22:22:42 2013 +0200 @@ -138,7 +138,7 @@ curInstruction = op; op.forEachInput(useProc); - if (op.hasCall()) { + if (op.destroysCallerSavedRegisters()) { for (Register register : frameMap.registerConfig.getCallerSaveRegisters()) { curRegistersLive[register.number] = null; } diff -r ca34e36c53e8 -r 56c12e0c15c1 src/cpu/x86/vm/graalRuntime_x86.cpp --- a/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Apr 30 21:38:48 2013 +0200 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Apr 30 22:22:42 2013 +0200 @@ -889,18 +889,6 @@ break; } - case stub_printf_id: { - __ enter(); - oop_maps = new OopMapSet(); - OopMap* oop_map = save_live_registers(sasm, 4); - int call_offset = __ call_RT(noreg, noreg, (address)stub_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3); - oop_maps->add_gc_map(call_offset, oop_map); - restore_live_registers(sasm); - __ leave(); - __ ret(0); - break; - } - case log_primitive_id: { __ enter(); oop_maps = new OopMapSet(); diff -r ca34e36c53e8 -r 56c12e0c15c1 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Apr 30 21:38:48 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Apr 30 22:22:42 2013 +0200 @@ -762,7 +762,6 @@ set_address("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::monitorexit_id)); set_address("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::verify_oop_id)); set_address("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::vm_error_id)); - set_address("deoptimizeStub", SharedRuntime::deopt_blob()->uncommon_trap()); set_address("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::unwind_exception_call_id)); set_address("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::OSR_migration_end_id)); set_address("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_null_pointer_exception_id)); @@ -777,7 +776,6 @@ set_address("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id)); set_address("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id)); set_address("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id)); - set_address("stubPrintfStub", GraalRuntime::entry_for(GraalRuntime::stub_printf_id)); set_address("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock()); set_address("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock()); set_address("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt()); @@ -788,6 +786,8 @@ set_address("newMultiArrayAddress", GraalRuntime::new_multi_array); set_address("registerFinalizerAddress", SharedRuntime::register_finalizer); set_address("threadIsInterruptedAddress", GraalRuntime::thread_is_interrupted); + set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap()); + set_address("stubPrintfAddress", GraalRuntime::stub_printf); set_int("deoptReasonNone", Deoptimization::Reason_none); set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check); diff -r ca34e36c53e8 -r 56c12e0c15c1 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Tue Apr 30 21:38:48 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Tue Apr 30 22:22:42 2013 +0200 @@ -570,7 +570,7 @@ tty->print(buf, v1, v2, v3); JRT_END -JRT_LEAF(void, GraalRuntime::stub_printf(JavaThread* thread, jlong format, jlong v1, jlong v2, jlong v3)) +JRT_LEAF(void, GraalRuntime::stub_printf(jlong format, jlong v1, jlong v2, jlong v3)) ResourceMark rm; char *buf = (char*) (address) format; tty->print(buf, v1, v2, v3); diff -r ca34e36c53e8 -r 56c12e0c15c1 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Tue Apr 30 21:38:48 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Tue Apr 30 22:22:42 2013 +0200 @@ -94,7 +94,6 @@ stub(create_out_of_bounds_exception) \ stub(log_object) \ stub(log_printf) \ - stub(stub_printf) \ stub(log_primitive) \ stub(identity_hash_code) \ stub(wb_pre_call) \ @@ -138,7 +137,6 @@ static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); static void vm_error(JavaThread* thread, oop where, oop format, jlong value); static void log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); - static void stub_printf(JavaThread* thread, jlong format, jlong v1, jlong v2, jlong v3); static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); static void wb_pre_call(JavaThread* thread, oopDesc* obj); static void wb_post_call(JavaThread* thread, oopDesc* obj, void* card); @@ -158,6 +156,7 @@ static void new_array(JavaThread* thread, Klass* klass, jint length); static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims); static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte); + static void stub_printf(jlong format, jlong v1, jlong v2, jlong v3); // initialization static void initialize(BufferBlob* blob);