# HG changeset patch # User Doug Simon # Date 1366573269 -7200 # Node ID 9be78aeab2e19e371b24f306f7620892bbbb3f92 # Parent 2ff3499d408e6722a9c875c549e64207b38f51e4 temporaries are recorded for compiled stubs, allowing for better register allocation around calls to such stubs (GRAAL-210) diff -r 2ff3499d408e -r 9be78aeab2e1 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 Sun Apr 21 21:37:40 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Sun Apr 21 21:41:09 2013 +0200 @@ -28,6 +28,7 @@ import static com.oracle.graal.phases.GraalOptions.*; import java.lang.reflect.*; +import java.util.*; import sun.misc.*; @@ -42,10 +43,13 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.*; /** @@ -154,6 +158,30 @@ if (deoptimizationRescueSlot != null) { tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot)); } + + Stub stub = runtime().asStub(lirGen.method()); + if (stub != null) { + final Set definedRegisters = new HashSet<>(); + ValueProcedure defProc = new ValueProcedure() { + + @Override + public Value doValue(Value value) { + if (ValueUtil.isRegister(value)) { + final Register reg = ValueUtil.asRegister(value); + definedRegisters.add(reg); + } + return value; + } + }; + for (Block block : lir.codeEmittingOrder()) { + for (LIRInstruction op : lir.lir(block)) { + op.forEachTemp(defProc); + op.forEachOutput(defProc); + } + } + stub.initDefinedRegisters(definedRegisters); + } + return tasm; } diff -r 2ff3499d408e -r 9be78aeab2e1 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 Sun Apr 21 21:37:40 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Sun Apr 21 21:41:09 2013 +0200 @@ -105,8 +105,7 @@ /* arg0: object */ javaCallingConvention(Kind.Object, /* arg1: lock */ word)); - addRuntimeCall(NEW_ARRAY, 0L, - /* temps */ null, + addStubCall(NEW_ARRAY, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); @@ -117,8 +116,7 @@ /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); - addRuntimeCall(NEW_INSTANCE, 0L, - /* temps */ null, + addStubCall(NEW_INSTANCE, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word)); diff -r 2ff3499d408e -r 9be78aeab2e1 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 Sun Apr 21 21:37:40 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Sun Apr 21 21:41:09 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.target.*; @@ -51,7 +53,7 @@ /** * Where the stub gets its arguments and where it places its result. */ - public final CallingConvention cc; + private CallingConvention cc; private final CompilerToVM vm; @@ -87,12 +89,28 @@ public void finalizeAddress(Backend backend) { if (address == 0) { assert stub != null : "linkage without an address must be a stub"; - address = stub.getAddress(backend); + InstalledCode code = stub.getCode(backend); + + Value[] argumentLocations = new Value[cc.getArgumentCount()]; + for (int i = 0; i < argumentLocations.length; i++) { + argumentLocations[i] = cc.getArgument(i); + } + + Set definedRegisters = stub.getDefinedRegisters(); + Value[] temporaryLocations = new Value[definedRegisters.size()]; + int i = 0; + for (Register reg : definedRegisters) { + temporaryLocations[i++] = reg.asValue(); + } + // Update calling convention with temporaries + cc = new CallingConvention(temporaryLocations, cc.getStackSize(), cc.getReturn(), argumentLocations); + address = code.getStart(); } } @Override public boolean preservesRegisters() { - return stub == null; + assert address != 0; + return true; } } diff -r 2ff3499d408e -r 9be78aeab2e1 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 Sun Apr 21 21:37:40 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Sun Apr 21 21:41:09 2013 +0200 @@ -271,6 +271,17 @@ } /** + * Registers the details for linking a call to a compiled {@link Stub}. + * + * @param descriptor name and signature of the call + * @param ret where the call returns its result + * @param args where arguments are passed to the call + */ + protected RuntimeCallTarget addStubCall(Descriptor descriptor, Value ret, Value... args) { + return addRuntimeCall(descriptor, 0L, null, ret, args); + } + + /** * Registers the details for linking a runtime call. * * @param descriptor name and signature of the call diff -r 2ff3499d408e -r 9be78aeab2e1 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 Sun Apr 21 21:37:40 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Sun Apr 21 21:41:09 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.stubs; +import java.util.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -29,6 +30,7 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; @@ -64,11 +66,26 @@ /** * The code installed for the stub. */ - protected InstalledCode stubCode; + protected InstalledCode code; /** - * Creates a new stub container. The new stub still needs to be - * {@linkplain #getAddress(Backend) installed}. + * The registers defined by this stub. + */ + private Set definedRegisters; + + public void initDefinedRegisters(Set registers) { + assert registers != null; + assert definedRegisters == null : "cannot redefine"; + definedRegisters = registers; + } + + public Set getDefinedRegisters() { + assert definedRegisters != null : "not yet initialized"; + return definedRegisters; + } + + /** + * Creates a new stub container.. * * @param linkage linkage details for a call to the stub */ @@ -100,37 +117,43 @@ } /** - * Ensures the code for this stub is installed. - * - * @return the entry point address for calls to this stub + * Gets the code for this stub, compiling it first if necessary. */ - public synchronized long getAddress(Backend backend) { - if (stubCode == null) { - Arguments args = makeArguments(stubInfo); - SnippetTemplate template = template(args); - StructuredGraph graph = template.copySpecializedGraph(); - - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL, - new SpeculationLog()); - - stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable() { + public synchronized InstalledCode getCode(final Backend backend) { + if (code == null) { + Debug.sandbox("CompilingStub", new Object[]{runtime(), getMethod()}, DebugScope.getConfig(), new Runnable() { @Override - public InstalledCode call() { - InstalledCode installedCode = runtime().addMethod(getMethod(), compResult); - assert installedCode != null : "error installing stub " + getMethod(); - if (Debug.isDumpEnabled()) { - Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); - } - return installedCode; + public void run() { + + Arguments args = makeArguments(stubInfo); + SnippetTemplate template = template(args); + StructuredGraph graph = template.copySpecializedGraph(); + + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, + OptimisticOptimizations.ALL, new SpeculationLog()); + + assert definedRegisters != null; + code = Debug.scope("CodeInstall", new Callable() { + + @Override + public InstalledCode call() { + InstalledCode installedCode = runtime().addMethod(getMethod(), compResult); + assert installedCode != null : "error installing stub " + getMethod(); + if (Debug.isDumpEnabled()) { + Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); + } + return installedCode; + } + }); + } }); - - assert stubCode != null : "error installing stub " + getMethod(); + assert code != null : "error installing stub " + getMethod(); } - return stubCode.getStart(); + return code; } }