changeset 9415:016523a011b7

simplified register preservation in compiled stubs to avoid the need for using ParametersOp
author Doug Simon <doug.simon@oracle.com>
date Mon, 29 Apr 2013 18:26:39 +0200
parents a58860b72b1f
children 16c354398d09 ffa27c3058e9
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/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegisterPreservationOp.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java
diffstat 5 files changed, 87 insertions(+), 149 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Apr 29 18:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Mon Apr 29 18:26:39 2013 +0200
@@ -163,18 +163,14 @@
         Stub stub = runtime().asStub(lirGen.method());
         if (stub != null) {
 
-            List<AMD64RegisterPreservationOp> registerPreservations = new ArrayList<>();
-            final Set<Register> definedRegisters = gatherDefinedRegisters(lir, registerPreservations);
+            final Set<Register> definedRegisters = gatherDefinedRegisters(lir);
             stub.initDefinedRegisters(definedRegisters);
 
-            // Eliminate unnecessary register preservation
-            for (AMD64RegisterPreservationOp op : registerPreservations) {
-                op.doNotPreserve(definedRegisters);
-            }
-
-            // Record where preserved registers are saved
-            for (Map.Entry<LIRFrameState, AMD64RestoreRegistersOp> e : gen.calleeSaveInfo.entrySet()) {
-                e.getValue().describePreservation(e.getKey().debugInfo(), frameMap);
+            // Eliminate unnecessary register preservation and
+            // record where preserved registers are saved
+            for (Map.Entry<LIRFrameState, AMD64SaveRegistersOp> e : gen.calleeSaveInfo.entrySet()) {
+                AMD64SaveRegistersOp save = e.getValue();
+                save.updateAndDescribePreservation(definedRegisters, e.getKey().debugInfo(), frameMap);
             }
         }
 
@@ -185,10 +181,9 @@
      * Finds all the registers that are defined by some given LIR.
      * 
      * @param lir the LIR to examine
-     * @param registerPreservations register preservation operations in {@code lir} are added to this list
      * @return the registers that are defined by or used as temps for any instruction in {@code lir}
      */
-    private static Set<Register> gatherDefinedRegisters(LIR lir, List<AMD64RegisterPreservationOp> registerPreservations) {
+    private static Set<Register> gatherDefinedRegisters(LIR lir) {
         final Set<Register> definedRegisters = new HashSet<>();
         ValueProcedure defProc = new ValueProcedure() {
 
@@ -203,11 +198,8 @@
         };
         for (Block block : lir.codeEmittingOrder()) {
             for (LIRInstruction op : lir.lir(block)) {
-                if (op instanceof AMD64RegisterPreservationOp) {
-                    // Don't consider these ops as definitions
-                    registerPreservations.add((AMD64RegisterPreservationOp) op);
-                } else if (op instanceof ParametersOp) {
-                    // Don't consider these ops as definitions
+                if (op instanceof ParametersOp) {
+                    // Don't consider this as a definition
                 } else {
                     op.forEachTemp(defProc);
                     op.forEachOutput(defProc);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Apr 29 18:25:53 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Apr 29 18:26:39 2013 +0200
@@ -176,7 +176,7 @@
      * Map from debug infos that need to be updated with callee save information to the operations
      * that provide the information.
      */
-    Map<LIRFrameState, AMD64RestoreRegistersOp> calleeSaveInfo = new HashMap<>();
+    Map<LIRFrameState, AMD64SaveRegistersOp> calleeSaveInfo = new HashMap<>();
 
     private LIRFrameState currentRuntimeCallInfo;
 
@@ -193,29 +193,16 @@
     public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args) {
         boolean needsCalleeSave = ((HotSpotRuntimeCallTarget) callTarget).isCRuntimeCall();
 
-        RegisterValue[] savedRegisters = null;
+        AMD64SaveRegistersOp save = null;
         StackSlot[] savedRegisterLocations = null;
         if (needsCalleeSave) {
-            Register returnReg = isRegister(cc.getReturn()) ? asRegister(cc.getReturn()) : null;
-            Set<Register> registers = new HashSet<>(Arrays.asList(frameMap.registerConfig.getAllocatableRegisters()));
-            if (returnReg != null) {
-                registers.remove(returnReg);
-            }
-
-            savedRegisters = new RegisterValue[registers.size()];
+            Register[] savedRegisters = frameMap.registerConfig.getAllocatableRegisters();
             savedRegisterLocations = new StackSlot[savedRegisters.length];
-            int savedRegisterIndex = 0;
-            for (Register reg : registers) {
-                assert reg.isCpu() || reg.isFpu();
-                savedRegisters[savedRegisterIndex++] = reg.asValue(reg.isCpu() ? Kind.Long : Kind.Double);
-            }
-
-            append(new ParametersOp(savedRegisters));
             for (int i = 0; i < savedRegisters.length; i++) {
                 StackSlot spillSlot = frameMap.allocateSpillSlot(Kind.Long);
                 savedRegisterLocations[i] = spillSlot;
             }
-            AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations);
+            save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations);
             append(save);
 
             Value thread = args[0];
@@ -231,8 +218,8 @@
             AMD64HotSpotCRuntimeCallEpilogueOp op = new AMD64HotSpotCRuntimeCallEpilogueOp(thread);
             append(op);
 
-            AMD64RestoreRegistersOp restore = new AMD64RestoreRegistersOp(savedRegisterLocations.clone(), savedRegisters.clone());
-            AMD64RestoreRegistersOp oldValue = calleeSaveInfo.put(currentRuntimeCallInfo, restore);
+            AMD64RestoreRegistersOp restore = new AMD64RestoreRegistersOp(savedRegisterLocations.clone(), save);
+            AMD64SaveRegistersOp oldValue = calleeSaveInfo.put(currentRuntimeCallInfo, save);
             assert oldValue == null;
             append(restore);
         }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegisterPreservationOp.java	Mon Apr 29 18:25:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2013, 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 java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.asm.*;
-
-/**
- * Base class for the operations that save or restore registers around another operation that may
- * potentially destroy any register (e.g., a call).
- */
-public abstract class AMD64RegisterPreservationOp extends AMD64LIRInstruction {
-
-    protected static void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value[] destination, Value[] source) {
-        for (int i = 0; i < destination.length; i++) {
-            if (destination[i] != null) {
-                AMD64Move.move(tasm, masm, destination[i], source[i]);
-            } else {
-                assert source[i] == null;
-            }
-        }
-    }
-
-    protected static void doNotPreserve(Set<Register> registers, RegisterValue[] registerValues, StackSlot[] slots) {
-        for (int i = 0; i < slots.length; i++) {
-            if (registerValues[i] != null) {
-                if (registers.contains(registerValues[i].getRegister())) {
-                    registerValues[i] = null;
-                    slots[i] = null;
-                }
-            }
-        }
-    }
-
-    /**
-     * Records that no registers in {@code registers} need to be preserved.
-     */
-    public abstract void doNotPreserve(Set<Register> registers);
-}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Mon Apr 29 18:25:53 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java	Mon Apr 29 18:26:39 2013 +0200
@@ -24,11 +24,8 @@
 
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import java.util.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 
@@ -36,49 +33,32 @@
  * Restores registers from stack slots.
  */
 @Opcode("RESTORE_REGISTER")
-public final class AMD64RestoreRegistersOp extends AMD64RegisterPreservationOp {
+public final class AMD64RestoreRegistersOp extends AMD64LIRInstruction {
+
+    /**
+     * The slots from which the registers are restored.
+     */
+    @Use(STACK) protected final StackSlot[] slots;
 
-    @Use(STACK) protected StackSlot[] source;
-    @Def(REG) protected RegisterValue[] destination;
+    /**
+     * The operation that saved the registers restored by this operation.
+     */
+    private final AMD64SaveRegistersOp save;
 
-    public AMD64RestoreRegistersOp(StackSlot[] source, RegisterValue[] destination) {
-        this.source = source;
-        this.destination = destination;
+    public AMD64RestoreRegistersOp(StackSlot[] source, AMD64SaveRegistersOp save) {
+        this.slots = source;
+        this.save = save;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        emitCode(tasm, masm, destination, source);
-    }
-
-    @Override
-    public void doNotPreserve(Set<Register> registers) {
-        doNotPreserve(registers, destination, source);
-    }
-
-    /**
-     * Updates {@code debugInfo} with a description of where each preserved register is saved.
-     */
-    public void describePreservation(DebugInfo debugInfo, FrameMap frameMap) {
-        int preserved = 0;
-        for (RegisterValue r : destination) {
-            if (r != null) {
-                preserved++;
+        Register[] savedRegisters = save.savedRegisters;
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                StackSlot input = slots[i];
+                RegisterValue result = savedRegisters[i].asValue(input.getKind());
+                AMD64Move.move(tasm, masm, result, input);
             }
         }
-        if (preserved != 0) {
-            Register[] keys = new Register[preserved];
-            int[] values = new int[keys.length];
-            int mapIndex = 0;
-            for (int i = 0; i < source.length; i++) {
-                if (destination[i] != null) {
-                    keys[mapIndex] = destination[i].getRegister();
-                    values[mapIndex] = frameMap.indexForStackSlot(source[i]);
-                    mapIndex++;
-                }
-            }
-            assert mapIndex == preserved;
-            debugInfo.setCalleeSaveInfo(new RegisterSaveLayout(keys, values));
-        }
     }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Mon Apr 29 18:25:53 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Mon Apr 29 18:26:39 2013 +0200
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.asm.*;
 
@@ -35,24 +36,65 @@
  * Saves registers to stack slots.
  */
 @Opcode("SAVE_REGISTER")
-public final class AMD64SaveRegistersOp extends AMD64RegisterPreservationOp {
+public final class AMD64SaveRegistersOp extends AMD64LIRInstruction {
+
+    /**
+     * The registers (potentially) saved by this operation.
+     */
+    protected final Register[] savedRegisters;
 
-    @Use(REG) protected RegisterValue[] source;
-    @Def(STACK) protected StackSlot[] destination;
+    /**
+     * The slots to which the registers are saved.
+     */
+    @Def(STACK) protected final StackSlot[] slots;
 
-    public AMD64SaveRegistersOp(RegisterValue[] source, StackSlot[] destination) {
-        this.source = source;
-        this.destination = destination;
+    public AMD64SaveRegistersOp(Register[] savedRegisters, StackSlot[] slots) {
+        this.savedRegisters = savedRegisters;
+        this.slots = slots;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        emitCode(tasm, masm, destination, source);
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                StackSlot result = slots[i];
+                RegisterValue input = savedRegisters[i].asValue(result.getKind());
+                AMD64Move.move(tasm, masm, result, input);
+            } else {
+                assert savedRegisters[i] == null;
+            }
+        }
     }
 
-    @Override
-    public void doNotPreserve(Set<Register> registers) {
-        doNotPreserve(registers, source, destination);
+    /**
+     * Prunes the set of registers saved by this operation to exclude those in {@code notSaved} and
+     * updates {@code debugInfo} with a {@linkplain DebugInfo#getCalleeSaveInfo() description} of
+     * where each preserved register is saved.
+     */
+    public void updateAndDescribePreservation(Set<Register> notSaved, DebugInfo debugInfo, FrameMap frameMap) {
+        int preserved = 0;
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                if (notSaved.contains(savedRegisters[i])) {
+                    savedRegisters[i] = null;
+                } else {
+                    preserved++;
+                }
+            }
+        }
+        if (preserved != 0) {
+            Register[] keys = new Register[preserved];
+            int[] values = new int[keys.length];
+            int mapIndex = 0;
+            for (int i = 0; i < savedRegisters.length; i++) {
+                if (savedRegisters[i] != null) {
+                    keys[mapIndex] = savedRegisters[i];
+                    values[mapIndex] = frameMap.indexForStackSlot(slots[i]);
+                    mapIndex++;
+                }
+            }
+            assert mapIndex == preserved;
+            debugInfo.setCalleeSaveInfo(new RegisterSaveLayout(keys, values));
+        }
     }
-
 }