< prev index next >

src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java

Print this page

        

*** 20,73 **** * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.vm.ci.hotspot.sparc; ! import static jdk.vm.ci.sparc.SPARC.*; ! ! import java.util.*; ! ! import jdk.vm.ci.code.*; ! import jdk.vm.ci.code.CallingConvention.*; ! import jdk.vm.ci.common.*; ! import jdk.vm.ci.hotspot.*; ! import jdk.vm.ci.meta.*; ! import jdk.vm.ci.sparc.*; public class SPARCHotSpotRegisterConfig implements RegisterConfig { private final Architecture architecture; private final Register[] allocatable; private final RegisterAttributes[] attributesMap; @Override public Register[] getAllocatableRegisters() { return allocatable.clone(); } public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) { ArrayList<Register> list = new ArrayList<>(); for (Register reg : registers) { if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { - // Special treatment for double precision - // TODO: This is wasteful it uses only half of the registers as float. - if (kind == JavaKind.Double) { - if (reg.getRegisterCategory().equals(FPUd)) { list.add(reg); } - } else if (kind == JavaKind.Float) { - if (reg.getRegisterCategory().equals(FPUs)) { - list.add(reg); - } - } else { - list.add(reg); - } - } } - Register[] ret = list.toArray(new Register[list.size()]); return ret; } @Override --- 20,121 ---- * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.vm.ci.hotspot.sparc; ! import static jdk.vm.ci.code.CallingConvention.Type.JavaCall; ! import static jdk.vm.ci.code.CallingConvention.Type.JavaCallee; ! import static jdk.vm.ci.code.CallingConvention.Type.NativeCall; ! import static jdk.vm.ci.meta.JavaKind.Void; ! import static jdk.vm.ci.meta.Value.ILLEGAL; ! import static jdk.vm.ci.sparc.SPARC.REGISTER_SAFE_AREA_SIZE; ! import static jdk.vm.ci.sparc.SPARC.d0; ! import static jdk.vm.ci.sparc.SPARC.d2; ! import static jdk.vm.ci.sparc.SPARC.d4; ! import static jdk.vm.ci.sparc.SPARC.d6; ! import static jdk.vm.ci.sparc.SPARC.f0; ! import static jdk.vm.ci.sparc.SPARC.f1; ! import static jdk.vm.ci.sparc.SPARC.f2; ! import static jdk.vm.ci.sparc.SPARC.f3; ! import static jdk.vm.ci.sparc.SPARC.f4; ! import static jdk.vm.ci.sparc.SPARC.f5; ! import static jdk.vm.ci.sparc.SPARC.f6; ! import static jdk.vm.ci.sparc.SPARC.f7; ! import static jdk.vm.ci.sparc.SPARC.g0; ! import static jdk.vm.ci.sparc.SPARC.g2; ! import static jdk.vm.ci.sparc.SPARC.g6; ! import static jdk.vm.ci.sparc.SPARC.i0; ! import static jdk.vm.ci.sparc.SPARC.i1; ! import static jdk.vm.ci.sparc.SPARC.i2; ! import static jdk.vm.ci.sparc.SPARC.i3; ! import static jdk.vm.ci.sparc.SPARC.i4; ! import static jdk.vm.ci.sparc.SPARC.i5; ! import static jdk.vm.ci.sparc.SPARC.i6; ! import static jdk.vm.ci.sparc.SPARC.i7; ! import static jdk.vm.ci.sparc.SPARC.l0; ! import static jdk.vm.ci.sparc.SPARC.l1; ! import static jdk.vm.ci.sparc.SPARC.l2; ! import static jdk.vm.ci.sparc.SPARC.l3; ! import static jdk.vm.ci.sparc.SPARC.l4; ! import static jdk.vm.ci.sparc.SPARC.l5; ! import static jdk.vm.ci.sparc.SPARC.l6; ! import static jdk.vm.ci.sparc.SPARC.l7; ! import static jdk.vm.ci.sparc.SPARC.o0; ! import static jdk.vm.ci.sparc.SPARC.o1; ! import static jdk.vm.ci.sparc.SPARC.o2; ! import static jdk.vm.ci.sparc.SPARC.o3; ! import static jdk.vm.ci.sparc.SPARC.o4; ! import static jdk.vm.ci.sparc.SPARC.o5; ! import static jdk.vm.ci.sparc.SPARC.sp; ! ! import java.util.ArrayList; ! import java.util.Arrays; ! import java.util.Collections; ! import java.util.HashSet; ! ! import jdk.vm.ci.code.Architecture; ! import jdk.vm.ci.code.CallingConvention; ! import jdk.vm.ci.code.CallingConvention.Type; ! import jdk.vm.ci.code.Register; ! import jdk.vm.ci.code.RegisterAttributes; ! import jdk.vm.ci.code.RegisterConfig; ! import jdk.vm.ci.code.StackSlot; ! import jdk.vm.ci.code.TargetDescription; ! import jdk.vm.ci.common.JVMCIError; ! import jdk.vm.ci.hotspot.HotSpotVMConfig; ! import jdk.vm.ci.meta.AllocatableValue; ! import jdk.vm.ci.meta.JavaKind; ! import jdk.vm.ci.meta.JavaType; ! import jdk.vm.ci.meta.LIRKind; ! import jdk.vm.ci.meta.PlatformKind; ! import jdk.vm.ci.sparc.SPARC; public class SPARCHotSpotRegisterConfig implements RegisterConfig { private final Architecture architecture; private final Register[] allocatable; private final RegisterAttributes[] attributesMap; + /** + * Does native code (C++ code) spill arguments in registers to the parent frame? + */ + private final boolean addNativeRegisterArgumentSlots; + @Override public Register[] getAllocatableRegisters() { return allocatable.clone(); } public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) { ArrayList<Register> list = new ArrayList<>(); for (Register reg : registers) { if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) { list.add(reg); } } Register[] ret = list.toArray(new Register[list.size()]); return ret; } @Override
*** 76,155 **** } private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5}; private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5}; ! private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7}; private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null}; // @formatter:off ! private final Register[] callerSaveRegisters = ! {g1, g2, g3, g4, g5, g6, g7, ! o0, o1, o2, o3, o4, o5, o7, ! f0, f1, f2, f3, f4, f5, f6, f7, ! f8, f9, f10, f11, f12, f13, f14, f15, ! f16, f17, f18, f19, f20, f21, f22, f23, ! f24, f25, f26, f27, f28, f29, f30, f31, ! d32, d34, d36, d38, d40, d42, d44, d46, ! d48, d50, d52, d54, d56, d58, d60, d62}; ! // @formatter:on /** * Registers saved by the callee. This lists all L and I registers which are saved in the * register window. */ ! private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, i6, i7}; ! ! private static Register[] initAllocatable(boolean reserveForHeapBase) { ! Register[] registers = null; ! if (reserveForHeapBase) { ! // @formatter:off ! registers = new Register[]{ ! // TODO this is not complete ! // o7 cannot be used as register because it is always overwritten on call ! // and the current register handler would ignore this fact if the called ! // method still does not modify registers, in fact o7 is modified by the Call instruction ! // There would be some extra handlin necessary to be able to handle the o7 properly for local usage ! g1, g4, g5, ! o0, o1, o2, o3, o4, o5, /*o6,o7,*/ l0, l1, l2, l3, l4, l5, l6, l7, ! i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/ ! //f0, f1, f2, f3, f4, f5, f6, f7, ! f8, f9, f10, f11, f12, f13, f14, f15, ! f16, f17, f18, f19, f20, f21, f22, f23, ! f24, f25, f26, f27, f28, f29, f30, f31, ! d32, d34, d36, d38, d40, d42, d44, d46, ! d48, d50, d52, d54, d56, d58, d60, d62 ! }; ! // @formatter:on ! } else { ! // @formatter:off ! registers = new Register[]{ ! // TODO this is not complete ! g1, g4, g5, ! o0, o1, o2, o3, o4, o5, /*o6, o7,*/ ! l0, l1, l2, l3, l4, l5, l6, l7, ! i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/ ! // f0, f1, f2, f3, f4, f5, f6, f7 ! f8, f9, f10, f11, f12, f13, f14, f15, ! f16, f17, f18, f19, f20, f21, f22, f23, ! f24, f25, f26, f27, f28, f29, f30, f31, ! d32, d34, d36, d38, d40, d42, d44, d46, ! d48, d50, d52, d54, d56, d58, d60, d62 ! }; // @formatter:on } return registers; } ! public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) { ! this(target, initAllocatable(config.useCompressedOops)); } ! public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) { ! this.architecture = target.arch; this.allocatable = allocatable.clone(); attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters); } @Override public Register[] getCallerSaveRegisters() { --- 124,184 ---- } private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5}; private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5}; ! private final Register[] fpuFloatParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7}; private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null}; + // @formatter:off ! private final Register[] callerSaveRegisters; /** * Registers saved by the callee. This lists all L and I registers which are saved in the * register window. */ ! private final Register[] calleeSaveRegisters = { l0, l1, l2, l3, l4, l5, l6, l7, ! i0, i1, i2, i3, i4, i5, i6, i7}; // @formatter:on + + private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) { + Register[] allRegisters = arch.getAvailableValueRegisters(); + Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 4 : 3)]; + + int idx = 0; + for (Register reg : allRegisters) { + if (reg.equals(sp) || reg.equals(g2) || reg.equals(g0)) { + // skip g0, stack pointer and thread register + continue; + } + if (reserveForHeapBase && reg.equals(g6)) { + // skip heap base register + continue; + } + + registers[idx++] = reg; } + assert idx == registers.length; return registers; } ! public SPARCHotSpotRegisterConfig(Architecture arch, HotSpotVMConfig config) { ! this(arch, initAllocatable(arch, config.useCompressedOops), config); } ! public SPARCHotSpotRegisterConfig(Architecture arch, Register[] allocatable, HotSpotVMConfig config) { ! this.architecture = arch; this.allocatable = allocatable.clone(); + this.addNativeRegisterArgumentSlots = config.linuxOs; + HashSet<Register> callerSaveSet = new HashSet<>(); + Collections.addAll(callerSaveSet, arch.getAvailableValueRegisters()); + for (Register cs : calleeSaveRegisters) { + callerSaveSet.remove(cs); + } + this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]); attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters); } @Override public Register[] getCallerSaveRegisters() {
*** 170,194 **** throw new UnsupportedOperationException(); } @Override public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { ! if (type == Type.JavaCall || type == Type.NativeCall) { return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } ! if (type == Type.JavaCallee) { return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } throw JVMCIError.shouldNotReachHere(); } public Register[] getCallingConventionRegisters(Type type, JavaKind kind) { ! if (architecture.canStoreValue(FPUs, kind) || architecture.canStoreValue(FPUd, kind)) { ! return fpuParameterRegisters; ! } ! assert architecture.canStoreValue(CPU, kind); return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters; } private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) { AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; --- 199,233 ---- throw new UnsupportedOperationException(); } @Override public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { ! if (type == JavaCall || type == NativeCall) { return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } ! if (type == JavaCallee) { return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly); } throw JVMCIError.shouldNotReachHere(); } public Register[] getCallingConventionRegisters(Type type, JavaKind kind) { ! switch (kind) { ! case Boolean: ! case Byte: ! case Short: ! case Char: ! case Int: ! case Long: ! case Object: return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters; + case Double: + case Float: + return fpuFloatParameterRegisters; + default: + throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind); + } } private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) { AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
*** 211,264 **** Register register = generalParameterRegisters[currentGeneral++]; locations[i] = register.asValue(target.getLIRKind(kind)); } break; case Double: ! if (!stackOnly && currentFloating < fpuParameterRegisters.length) { if (currentFloating % 2 != 0) { // Make register number even to be a double reg currentFloating++; } Register register = fpuDoubleParameterRegisters[currentFloating]; currentFloating += 2; // Only every second is a double register locations[i] = register.asValue(target.getLIRKind(kind)); } break; case Float: ! if (!stackOnly && currentFloating < fpuParameterRegisters.length) { ! Register register = fpuParameterRegisters[currentFloating++]; locations[i] = register.asValue(target.getLIRKind(kind)); } break; default: throw JVMCIError.shouldNotReachHere(); } if (locations[i] == null) { // Stack slot is always aligned to its size in bytes but minimum wordsize ! int typeSize = SPARC.spillSlotSize(target, kind); currentStackOffset = roundUp(currentStackOffset, typeSize); ! int slotOffset = currentStackOffset + SPARC.REGISTER_SAFE_AREA_SIZE; ! locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), slotOffset, !type.out); currentStackOffset += typeSize; } } ! JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind(); ! AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind())); ! // Space where callee may spill outgoing parameters o0...o5 ! int lowerOutgoingSpace = Math.min(locations.length, 6) * target.wordSize; ! return new CallingConvention(currentStackOffset + lowerOutgoingSpace, returnLocation, locations); } private static int roundUp(int number, int mod) { return ((number + mod - 1) / mod) * mod; } @Override public Register getReturnRegister(JavaKind kind) { ! return getReturnRegister(kind, Type.JavaCallee); } private static Register getReturnRegister(JavaKind kind, Type type) { switch (kind) { case Boolean: --- 250,310 ---- Register register = generalParameterRegisters[currentGeneral++]; locations[i] = register.asValue(target.getLIRKind(kind)); } break; case Double: ! if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) { if (currentFloating % 2 != 0) { // Make register number even to be a double reg currentFloating++; } Register register = fpuDoubleParameterRegisters[currentFloating]; currentFloating += 2; // Only every second is a double register locations[i] = register.asValue(target.getLIRKind(kind)); } break; case Float: ! if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) { ! Register register = fpuFloatParameterRegisters[currentFloating++]; locations[i] = register.asValue(target.getLIRKind(kind)); } break; default: throw JVMCIError.shouldNotReachHere(); } if (locations[i] == null) { + LIRKind lirKind = target.getLIRKind(kind); // Stack slot is always aligned to its size in bytes but minimum wordsize ! int typeSize = lirKind.getPlatformKind().getSizeInBytes(); currentStackOffset = roundUp(currentStackOffset, typeSize); ! int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE; ! locations[i] = StackSlot.get(lirKind, slotOffset, !type.out); currentStackOffset += typeSize; } } ! JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind(); ! AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind())); ! ! int outArgSpillArea; ! if (type == NativeCall && addNativeRegisterArgumentSlots) { ! // Space for native callee which may spill our outgoing arguments ! outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize; ! } else { ! outArgSpillArea = 0; ! } ! return new CallingConvention(currentStackOffset + outArgSpillArea, returnLocation, locations); } private static int roundUp(int number, int mod) { return ((number + mod - 1) / mod) * mod; } @Override public Register getReturnRegister(JavaKind kind) { ! return getReturnRegister(kind, JavaCallee); } private static Register getReturnRegister(JavaKind kind, Type type) { switch (kind) { case Boolean:
*** 266,276 **** case Char: case Short: case Int: case Long: case Object: ! return type == Type.JavaCallee ? i0 : o0; case Float: return f0; case Double: return d0; case Void: --- 312,322 ---- case Char: case Short: case Int: case Long: case Object: ! return type == JavaCallee ? i0 : o0; case Float: return f0; case Double: return d0; case Void:
< prev index next >