< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java

Print this page
rev 56282 : [mq]: graal

@@ -59,10 +59,11 @@
 import org.graalvm.compiler.lir.LIRFrameState;
 import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
 import org.graalvm.compiler.lir.StandardOp.LabelOp;
+import org.graalvm.compiler.lir.StandardOp.RestoreRegistersOp;
 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
 import org.graalvm.compiler.lir.ValueConsumer;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 import org.graalvm.compiler.lir.framemap.FrameMap;
 import org.graalvm.compiler.nodes.UnwindNode;

@@ -74,19 +75,20 @@
 import org.graalvm.compiler.phases.tiers.SuitesProvider;
 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 import org.graalvm.compiler.word.Word;
 import jdk.internal.vm.compiler.word.Pointer;
 
+import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.code.CompiledCode;
 import jdk.vm.ci.code.Register;
-import jdk.vm.ci.code.RegisterSaveLayout;
 import jdk.vm.ci.code.StackSlot;
 import jdk.vm.ci.code.ValueUtil;
 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.Value;
 import jdk.vm.ci.runtime.JVMCICompiler;
 
 /**

@@ -423,37 +425,63 @@
     }
 
     /**
      * Finds all the registers that are defined by some given LIR.
      *
-     * @param lir the LIR to examine
+     * @param gen the result to examine
      * @return the registers that are defined by or used as temps for any instruction in {@code lir}
      */
-    protected final EconomicSet<Register> gatherDestroyedCallerRegisters(LIR lir) {
+    private EconomicSet<Register> gatherDestroyedCallerRegisters(HotSpotLIRGenerationResult gen) {
+        LIR lir = gen.getLIR();
+        final EconomicSet<Register> preservedRegisters = EconomicSet.create(Equivalence.IDENTITY);
         final EconomicSet<Register> destroyedRegisters = EconomicSet.create(Equivalence.IDENTITY);
         ValueConsumer defConsumer = new ValueConsumer() {
 
             @Override
             public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
                 if (ValueUtil.isRegister(value)) {
                     final Register reg = ValueUtil.asRegister(value);
+                    if (!preservedRegisters.contains(reg)) {
                     destroyedRegisters.add(reg);
                 }
             }
+            }
         };
+        boolean sawSaveRegisters = false;
         for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
             if (block == null) {
                 continue;
             }
+            // Ignore the effects of instructions bracketed by save/restore
+            SaveRegistersOp save = null;
             for (LIRInstruction op : lir.getLIRforBlock(block)) {
                 if (op instanceof LabelOp) {
                     // Don't consider this as a definition
+                } else if (op instanceof SaveRegistersOp) {
+                    save = (SaveRegistersOp) op;
+                    sawSaveRegisters = true;
+                    preservedRegisters.addAll(save.getSaveableRegisters());
+                } else if (op instanceof RestoreRegistersOp) {
+                    save = null;
+                    preservedRegisters.clear();
                 } else {
                     op.visitEachTemp(defConsumer);
                     op.visitEachOutput(defConsumer);
                 }
             }
+            assert save == null : "missing RestoreRegistersOp";
+        }
+
+        if (sawSaveRegisters) {
+            // The return value must be killed so it can be propagated out
+            CallingConvention cc = gen.getCallingConvention();
+            AllocatableValue returnValue = cc.getReturn();
+            if (returnValue != null) {
+                if (ValueUtil.isRegister(returnValue)) {
+                    destroyedRegisters.add(ValueUtil.asRegister(returnValue));
+                }
+            }
         }
         return translateToCallerRegisters(destroyedRegisters);
     }
 
     /**

@@ -462,34 +490,39 @@
      * register windows on SPARC). Registers which are not visible by the caller are removed.
      */
     protected abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
 
     /**
-     * Updates a given stub with respect to the registers it destroys.
-     * <p>
-     * Any entry in {@code calleeSaveInfo} that {@linkplain SaveRegistersOp#supportsRemove()
-     * supports} pruning will have {@code destroyedRegisters}
-     * {@linkplain SaveRegistersOp#remove(EconomicSet) removed} as these registers are declared as
-     * temporaries in the stub's {@linkplain ForeignCallLinkage linkage} (and thus will be saved by
-     * the stub's caller).
+     * Updates a given stub with respect to the registers it destroys by
+     * {@link #gatherDestroyedCallerRegisters(HotSpotLIRGenerationResult) computing the destroyed
+     * registers} and removing those registers from the {@linkplain SaveRegistersOp SaveRegistersOp}
+     * as these registers are declared as temporaries in the stub's {@linkplain ForeignCallLinkage
+     * linkage} (and thus will be saved by the stub's caller).
      *
      * @param stub the stub to update
-     * @param destroyedRegisters the registers destroyed by the stub
-     * @param calleeSaveInfo a map from debug infos to the operations that provide their
-     *            {@linkplain RegisterSaveLayout callee-save information}
+     * @param gen the HotSpotLIRGenerationResult being emitted
      * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a virtual
-     *            slot to a frame slot index
      */
-    protected void updateStub(Stub stub, EconomicSet<Register> destroyedRegisters, EconomicMap<LIRFrameState, SaveRegistersOp> calleeSaveInfo, FrameMap frameMap) {
+    protected void updateStub(Stub stub, HotSpotLIRGenerationResult gen, FrameMap frameMap) {
+        EconomicSet<Register> destroyedRegisters = gatherDestroyedCallerRegisters(gen);
+        EconomicMap<LIRFrameState, SaveRegistersOp> calleeSaveInfo = gen.getCalleeSaveInfo();
+
+        if (stub.getLinkage().needsDebugInfo() && calleeSaveInfo.isEmpty()) {
+            // This call is a safepoint but no register saving was done so we must ensure that all
+            // registers appear to be killed. The Native ABI may allow caller save registers but
+            // for HotSpot they must be described in a RegisterMap so they are accessible.
+            for (Register r : frameMap.getRegisterConfig().getCallerSaveRegisters()) {
+                destroyedRegisters.add(r);
+            }
+        }
+
         stub.initDestroyedCallerRegisters(destroyedRegisters);
 
         MapCursor<LIRFrameState, SaveRegistersOp> cursor = calleeSaveInfo.getEntries();
         while (cursor.advance()) {
             SaveRegistersOp save = cursor.getValue();
-            if (save.supportsRemove()) {
                 save.remove(destroyedRegisters);
-            }
             if (cursor.getKey() != LIRFrameState.NO_STATE) {
                 cursor.getKey().debugInfo().setCalleeSaveInfo(save.getMap(frameMap));
             }
         }
     }
< prev index next >