changeset 12610:62fb4919edc9

cleaned up mechanism for saving registers and updating the callee save maps in stubs
author Doug Simon <doug.simon@oracle.com>
date Fri, 25 Oct 2013 23:50:05 +0200
parents b81405d42861
children 63c378b7c1c3
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.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegistersPreservationOp.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java
diffstat 8 files changed, 146 insertions(+), 128 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Oct 25 19:24:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Oct 25 23:50:05 2013 +0200
@@ -45,12 +45,9 @@
 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.LabelOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.cfg.*;
 
 /**
  * HotSpot AMD64 specific backend.
@@ -183,54 +180,13 @@
         }
 
         if (stub != null) {
-
-            final Set<Register> definedRegisters = gatherDefinedRegisters(lir);
-            stub.initDestroyedRegisters(definedRegisters);
-
-            // Eliminate unnecessary register preservation and
-            // record where preserved registers are saved
-            for (Map.Entry<LIRFrameState, AMD64RegistersPreservationOp> e : gen.calleeSaveInfo.entrySet()) {
-                AMD64RegistersPreservationOp save = e.getValue();
-                DebugInfo info = e.getKey() == null ? null : e.getKey().debugInfo();
-                save.update(definedRegisters, info, frameMap);
-            }
+            Set<Register> definedRegisters = gatherDefinedRegisters(lir);
+            updateStub(stub, definedRegisters, gen.calleeSaveInfo, frameMap);
         }
 
         return tasm;
     }
 
-    /**
-     * Finds all the registers that are defined by some given LIR.
-     * 
-     * @param lir the LIR to examine
-     * @return the registers that are defined by or used as temps for any instruction in {@code lir}
-     */
-    private static Set<Register> gatherDefinedRegisters(LIR lir) {
-        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)) {
-                if (op instanceof LabelOp) {
-                    // Don't consider this as a definition
-                } else {
-                    op.forEachTemp(defProc);
-                    op.forEachOutput(defProc);
-                }
-            }
-        }
-        return definedRegisters;
-    }
-
     @Override
     public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) {
         AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Oct 25 19:24:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Oct 25 23:50:05 2013 +0200
@@ -49,6 +49,7 @@
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.PlaceholderOp;
+import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
@@ -210,7 +211,7 @@
      * Map from debug infos that need to be updated with callee save information to the operations
      * that provide the information.
      */
-    Map<LIRFrameState, AMD64RegistersPreservationOp> calleeSaveInfo = new HashMap<>();
+    Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = new HashMap<>();
 
     private LIRFrameState currentRuntimeCallInfo;
 
@@ -221,7 +222,7 @@
     }
 
     protected AMD64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, StackSlot[] savedRegisterLocations) {
-        AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations);
+        AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations, false);
         append(save);
         return save;
     }
@@ -269,7 +270,7 @@
             result = super.emitForeignCall(linkage, info, args);
             append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), thread));
         } else {
-            result = super.emitForeignCall(linkage, null, args);
+            result = super.emitForeignCall(linkage, info, args);
         }
 
         if (destroysRegisters) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Oct 25 19:24:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Oct 25 23:50:05 2013 +0200
@@ -37,6 +37,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.stubs.Stub;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.*;
@@ -164,8 +165,9 @@
 
         if (stub != null) {
             // SPARC stubs always enter a frame which saves the registers.
-            final Set<Register> definedRegisters = new HashSet<>();
-            stub.initDestroyedRegisters(definedRegisters);
+            Set<Register> destroyedRegisters = Collections.emptySet();
+            Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = Collections.emptyMap();
+            updateStub(stub, destroyedRegisters, calleeSaveInfo, frameMap);
         }
 
         return tasm;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Fri Oct 25 19:24:11 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java	Fri Oct 25 23:50:05 2013 +0200
@@ -22,13 +22,19 @@
  */
 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.*;
 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.StandardOp.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.word.*;
 
@@ -87,6 +93,63 @@
     public void completeInitialization() {
     }
 
+    /**
+     * Finds all the registers that are defined by some given LIR.
+     * 
+     * @param lir the LIR to examine
+     * @return the registers that are defined by or used as temps for any instruction in {@code lir}
+     */
+    protected static Set<Register> gatherDefinedRegisters(LIR lir) {
+        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)) {
+                if (op instanceof LabelOp) {
+                    // Don't consider this as a definition
+                } else {
+                    op.forEachTemp(defProc);
+                    op.forEachOutput(defProc);
+                }
+            }
+        }
+        return definedRegisters;
+    }
+
+    /**
+     * Updates a given stub with respect to the registers it destroys.
+     * 
+     * @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 frameMap used to {@linkplain FrameMap#indexForStackSlot(StackSlot) convert} a virtual
+     *            slot to a frame slot index
+     */
+    protected void updateStub(Stub stub, Set<Register> destroyedRegisters, Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo, FrameMap frameMap) {
+        stub.initDestroyedRegisters(destroyedRegisters);
+
+        // Eliminate unnecessary register preservation and
+        // record where preserved registers are saved
+        for (Map.Entry<LIRFrameState, SaveRegistersOp> e : calleeSaveInfo.entrySet()) {
+            SaveRegistersOp save = e.getValue();
+            save.remove(destroyedRegisters);
+            DebugInfo info = e.getKey() == null ? null : e.getKey().debugInfo();
+            if (info != null) {
+                info.setCalleeSaveInfo(save.getMap(frameMap));
+            }
+        }
+    }
+
     @Override
     public HotSpotProviders getProviders() {
         return (HotSpotProviders) super.getProviders();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegistersPreservationOp.java	Fri Oct 25 19:24:11 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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.lir.*;
-
-/**
- * Base class for operations that preserve a set of registers.
- */
-public abstract class AMD64RegistersPreservationOp extends AMD64LIRInstruction {
-
-    /**
-     * Prunes the set of registers preserved by this operation to exclude those in {@code ignored}
-     * and updates {@code debugInfo} with a {@linkplain DebugInfo#getCalleeSaveInfo() description}
-     * of where each preserved register is saved.
-     */
-    public abstract void update(Set<Register> ignored, DebugInfo debugInfo, FrameMap frameMap);
-}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Fri Oct 25 19:24:11 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java	Fri Oct 25 23:50:05 2013 +0200
@@ -29,13 +29,14 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
  * Saves registers to stack slots.
  */
 @Opcode("SAVE_REGISTER")
-public class AMD64SaveRegistersOp extends AMD64RegistersPreservationOp {
+public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveRegistersOp {
 
     /**
      * The registers (potentially) saved by this operation.
@@ -47,9 +48,15 @@
      */
     @Def(STACK) protected final StackSlot[] slots;
 
-    public AMD64SaveRegistersOp(Register[] savedRegisters, StackSlot[] slots) {
+    /**
+     * Specifies if {@link #remove(Set)} should have an effect.
+     */
+    protected final boolean forceAll;
+
+    public AMD64SaveRegistersOp(Register[] savedRegisters, StackSlot[] slots, boolean forceAll) {
         this.savedRegisters = savedRegisters;
         this.slots = slots;
+        this.forceAll = forceAll;
     }
 
     protected void saveRegister(TargetMethodAssembler tasm, AMD64MacroAssembler masm, StackSlot result, Register register) {
@@ -70,26 +77,33 @@
         return slots;
     }
 
-    /**
-     * Prunes the set of registers saved by this operation to exclude those in {@code ignored} and
-     * updates {@code debugInfo} with a {@linkplain DebugInfo#getCalleeSaveInfo() description} of
-     * where each preserved register is saved.
-     */
-    @Override
-    public void update(Set<Register> ignored, DebugInfo debugInfo, FrameMap frameMap) {
-        int preserved = 0;
-        for (int i = 0; i < savedRegisters.length; i++) {
-            if (savedRegisters[i] != null) {
-                if (ignored.contains(savedRegisters[i])) {
-                    savedRegisters[i] = null;
-                } else {
-                    preserved++;
+    public int remove(Set<Register> doNotSave) {
+        return prune(doNotSave, savedRegisters);
+    }
+
+    static int prune(Set<Register> toRemove, Register[] registers) {
+        int pruned = 0;
+        for (int i = 0; i < registers.length; i++) {
+            if (registers[i] != null) {
+                if (toRemove.contains(registers[i])) {
+                    registers[i] = null;
+                    pruned++;
                 }
             }
         }
-        if (preserved != 0) {
-            Register[] keys = new Register[preserved];
-            int[] values = new int[keys.length];
+        return pruned;
+    }
+
+    public RegisterSaveLayout getMap(FrameMap frameMap) {
+        int total = 0;
+        for (int i = 0; i < savedRegisters.length; i++) {
+            if (savedRegisters[i] != null) {
+                total++;
+            }
+        }
+        Register[] keys = new Register[total];
+        int[] values = new int[total];
+        if (total != 0) {
             int mapIndex = 0;
             for (int i = 0; i < savedRegisters.length; i++) {
                 if (savedRegisters[i] != null) {
@@ -98,10 +112,8 @@
                     mapIndex++;
                 }
             }
-            assert mapIndex == preserved;
-            if (debugInfo != null) {
-                debugInfo.setCalleeSaveInfo(new RegisterSaveLayout(keys, values));
-            }
+            assert mapIndex == total;
         }
+        return new RegisterSaveLayout(keys, values);
     }
 }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java	Fri Oct 25 19:24:11 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java	Fri Oct 25 23:50:05 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.lir.amd64.AMD64SaveRegistersOp.*;
 
 import java.util.*;
 
@@ -30,13 +31,14 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.asm.*;
 
 /**
  * Writes well known garbage values to registers.
  */
 @Opcode("ZAP_REGISTER")
-public final class AMD64ZapRegistersOp extends AMD64RegistersPreservationOp {
+public final class AMD64ZapRegistersOp extends AMD64LIRInstruction implements SaveRegistersOp {
 
     /**
      * The registers that are zapped.
@@ -63,17 +65,11 @@
         }
     }
 
-    /**
-     * Prunes the set of registers zapped by this operation to exclude those in {@code ignored}.
-     */
-    @Override
-    public void update(Set<Register> ignored, DebugInfo debugInfo, FrameMap frameMap) {
-        for (int i = 0; i < zappedRegisters.length; i++) {
-            if (zappedRegisters[i] != null) {
-                if (ignored.contains(zappedRegisters[i])) {
-                    zappedRegisters[i] = null;
-                }
-            }
-        }
+    public int remove(Set<Register> doNotSave) {
+        return prune(doNotSave, zappedRegisters);
+    }
+
+    public RegisterSaveLayout getMap(FrameMap frameMap) {
+        return new RegisterSaveLayout(new Register[0], new int[0]);
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Oct 25 19:24:11 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Oct 25 23:50:05 2013 +0200
@@ -24,6 +24,9 @@
 
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.graph.*;
@@ -139,6 +142,32 @@
     }
 
     /**
+     * An operation that saves registers to the stack. The set of saved registers can be
+     * {@linkplain #remove(Set) pruned} and a mapping from registers to the frame slots in which
+     * they are saved can be {@linkplain #getMap(FrameMap) retrieved}.
+     */
+    public interface SaveRegistersOp {
+
+        /**
+         * Prunes {@code doNotSave} from the registers saved by this operation.
+         * 
+         * @param doNotSave registers that should not be saved by this operation
+         * @return the number of registers pruned
+         */
+        int remove(Set<Register> doNotSave);
+
+        /**
+         * Gets a map from the saved registers saved by this operation to the frame slots in which
+         * they are saved.
+         * 
+         * @param frameMap used to {@linkplain FrameMap#indexForStackSlot(StackSlot) convert} a
+         *            virtual slot to a frame slot index
+         */
+        RegisterSaveLayout getMap(FrameMap frameMap);
+
+    }
+
+    /**
      * Placeholder for a LIR instruction that will be subsequently replaced.
      */
     public static class PlaceholderOp extends LIRInstruction {