changeset 9200:9be78aeab2e1

temporaries are recorded for compiled stubs, allowing for better register allocation around calls to such stubs (GRAAL-210)
author Doug Simon <doug.simon@oracle.com>
date Sun, 21 Apr 2013 21:41:09 +0200
parents 2ff3499d408e
children b6629b739a55 b9cf7d0b598e
files graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java
diffstat 5 files changed, 114 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- 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<Register> 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;
     }
 
--- 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));
 
--- 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<Register> 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;
     }
 }
--- 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
--- 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<Register> definedRegisters;
+
+    public void initDefinedRegisters(Set<Register> registers) {
+        assert registers != null;
+        assert definedRegisters == null : "cannot redefine";
+        definedRegisters = registers;
+    }
+
+    public Set<Register> 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<InstalledCode>() {
+    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<InstalledCode>() {
+
+                        @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;
     }
 }