# HG changeset patch # User Doug Simon # Date 1367252799 -7200 # Node ID 016523a011b796efcb5df457aa0e5235c1fa186c # Parent a58860b72b1fb5db0d405d0401901d43e620110b simplified register preservation in compiled stubs to avoid the need for using ParametersOp diff -r a58860b72b1f -r 016523a011b7 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 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 registerPreservations = new ArrayList<>(); - final Set definedRegisters = gatherDefinedRegisters(lir, registerPreservations); + final Set 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 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 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 gatherDefinedRegisters(LIR lir, List registerPreservations) { + private static Set gatherDefinedRegisters(LIR lir) { final Set 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); diff -r a58860b72b1f -r 016523a011b7 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 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 calleeSaveInfo = new HashMap<>(); + Map 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 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); } diff -r a58860b72b1f -r 016523a011b7 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegisterPreservationOp.java --- 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 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 registers); -} diff -r a58860b72b1f -r 016523a011b7 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java --- 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 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)); - } } } diff -r a58860b72b1f -r 016523a011b7 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 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 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 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)); + } } - }