# HG changeset patch # User Doug Simon # Date 1382737805 -7200 # Node ID 62fb4919edc9eaaa7d4f4bb5e29789c19dd8591c # Parent b81405d42861dfba8edca6cd347511839d3ba7a4 cleaned up mechanism for saving registers and updating the callee save maps in stubs diff -r b81405d42861 -r 62fb4919edc9 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 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 definedRegisters = gatherDefinedRegisters(lir); - stub.initDestroyedRegisters(definedRegisters); - - // Eliminate unnecessary register preservation and - // record where preserved registers are saved - for (Map.Entry e : gen.calleeSaveInfo.entrySet()) { - AMD64RegistersPreservationOp save = e.getValue(); - DebugInfo info = e.getKey() == null ? null : e.getKey().debugInfo(); - save.update(definedRegisters, info, frameMap); - } + Set 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 gatherDefinedRegisters(LIR lir) { - 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)) { - 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; diff -r b81405d42861 -r 62fb4919edc9 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- 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 calleeSaveInfo = new HashMap<>(); + Map 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) { diff -r b81405d42861 -r 62fb4919edc9 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- 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 definedRegisters = new HashSet<>(); - stub.initDestroyedRegisters(definedRegisters); + Set destroyedRegisters = Collections.emptySet(); + Map calleeSaveInfo = Collections.emptyMap(); + updateStub(stub, destroyedRegisters, calleeSaveInfo, frameMap); } return tasm; diff -r b81405d42861 -r 62fb4919edc9 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- 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 gatherDefinedRegisters(LIR lir) { + 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)) { + 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 destroyedRegisters, Map calleeSaveInfo, FrameMap frameMap) { + stub.initDestroyedRegisters(destroyedRegisters); + + // Eliminate unnecessary register preservation and + // record where preserved registers are saved + for (Map.Entry 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(); diff -r b81405d42861 -r 62fb4919edc9 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegistersPreservationOp.java --- 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 ignored, DebugInfo debugInfo, FrameMap frameMap); -} diff -r b81405d42861 -r 62fb4919edc9 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java --- 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 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 doNotSave) { + return prune(doNotSave, savedRegisters); + } + + static int prune(Set 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); } } diff -r b81405d42861 -r 62fb4919edc9 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java --- 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 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 doNotSave) { + return prune(doNotSave, zappedRegisters); + } + + public RegisterSaveLayout getMap(FrameMap frameMap) { + return new RegisterSaveLayout(new Register[0], new int[0]); } } diff -r b81405d42861 -r 62fb4919edc9 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java --- 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 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 {