< 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 >