Skip to content

Commit

Permalink
Remove RegType
Browse files Browse the repository at this point in the history
  • Loading branch information
feilongjiang committed Nov 12, 2022
1 parent 1c978e4 commit d5e2448
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 267 deletions.
9 changes: 7 additions & 2 deletions src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp
Expand Up @@ -62,9 +62,14 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) {
return abi;
}

enum class RegType {
INTEGER = 0,
FLOAT = 1,
STACK = 2
};

VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) {
int regtype = (type >> 8) << 8;
switch (static_cast<RegType>(regtype)) {
switch (static_cast<RegType>(type)) {
case RegType::INTEGER:
return ::as_Register(index)->as_VMReg();
case RegType::FLOAT:
Expand Down
15 changes: 0 additions & 15 deletions src/hotspot/cpu/riscv/foreignGlobals_riscv.hpp
Expand Up @@ -49,19 +49,4 @@ struct ABIDescriptor {
bool is_volatile_reg(FloatRegister reg) const;
};

enum class RegType {
INTEGER = 0,
FLOAT = 1 << 8,
STACK = 2 << 8
};

enum class StorageClass {
INTEGER_8 = static_cast<int>(RegType::INTEGER) | 8,
INTEGER_16 = static_cast<int>(RegType::INTEGER) | 16,
INTEGER_32 = static_cast<int>(RegType::INTEGER) | 32,
INTEGER_64 = static_cast<int>(RegType::INTEGER) | 64,
FLOAT_32 = static_cast<int>(RegType::FLOAT) | 32,
FLOAT_64 = static_cast<int>(RegType::FLOAT) | 64
};

#endif // CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP
70 changes: 30 additions & 40 deletions src/hotspot/cpu/riscv/upcallLinker_riscv.cpp
Expand Up @@ -113,20 +113,6 @@ static void restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescr
__ block_comment("} restore_callee_saved_regs ");
}

static GrowableArray<StorageClass> parse_reg_types(jobject jconv) {
oop conv_oop = JNIHandles::resolve_non_null(jconv);
objArrayOop ret_regs_oop = jdk_internal_foreign_abi_CallConv::retRegs(conv_oop);
int num_rets = ret_regs_oop->length();
GrowableArray<StorageClass> result{num_rets};
for (int i = 0; i < num_rets; i++) {
jint type = jdk_internal_foreign_abi_VMStorage::type(ret_regs_oop->obj_at(i));
assert(type >= static_cast<int>(StorageClass::INTEGER_8), "bad storage class.");
result.push(static_cast<StorageClass>(type));
}

return result;
}

// receive args from c function, and convert it into java calling convetion.
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
BasicType* in_sig_bt, int total_in_args,
Expand Down Expand Up @@ -232,6 +218,29 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
if (needs_return_buffer) {
assert(ret_buf_offset != -1, "no return buffer allocated");
__ la(abi._ret_buf_addr_reg, Address(sp, ret_buf_offset));

// When copy a floating-point data from memory into floating-point register,
// flw and fld have different behaviors:
// - flw will copy a 32-bit data into register and fill upper 32 bits of the register with 1s
// - fld will copy a 64-bit data without any alternation
// We might not know the current type of data being copied, so we fill all bits of return buffer with 1s.
// Therefore, a 32-bit floating-point data can also be copied by fld.
//
// See https://five-embeddev.com/riscv-isa-manual/latest/d.html#nanboxing
__ li(t0, -1L);
int offset = 0;
int unfilled_ret_buf_size = ret_buf_size;
while (unfilled_ret_buf_size >= 8) {
__ sd(t0, Address(sp, ret_buf_offset + offset));
offset += 8;
unfilled_ret_buf_size -= 8;
}
__ addi(t0, zr, 0XFF);
while (unfilled_ret_buf_size > 0) {
__ sb(t0, Address(sp, ret_buf_offset + offset));
offset++;
unfilled_ret_buf_size--;
}
}
// arg_shuffle will generate shuffle code that is used to
// to check how argument shuffle works, use -Xlog:foreign+upcall=trace.
Expand Down Expand Up @@ -284,35 +293,16 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
// move return value from return buffer to registers.
assert(ret_buf_offset != -1, "no return buffer allocated");
__ la(t0, Address(sp, ret_buf_offset));

GrowableArray<StorageClass> storages = parse_reg_types(jconv);
int offset = 0;
assert(storages.length() == call_regs._ret_regs.length(), "inconsistent length.");
for (int i = 0; i < call_regs._ret_regs.length(); i++) {
VMReg reg = call_regs._ret_regs.at(i);
StorageClass regtype = storages.at(i);
switch (regtype) {
case StorageClass::FLOAT_32:
__ flw(reg->as_FloatRegister(), Address(t0, offset));
break;
case StorageClass::FLOAT_64:
__ fld(reg->as_FloatRegister(), Address(t0, offset));
break;
case StorageClass::INTEGER_8:
__ lb(reg->as_Register(), Address(t0, offset));
break;
case StorageClass::INTEGER_16:
__ lh(reg->as_Register(), Address(t0, offset));
break;
case StorageClass::INTEGER_32:
__ lw(reg->as_Register(), Address(t0, offset));
break;
case StorageClass::INTEGER_64:
__ ld(reg->as_Register(), Address(t0, offset));
break;
default:
ShouldNotReachHere();
}
if (reg->is_Register()) {
__ ld(reg->as_Register(), Address(t0, offset));
} else if (reg->is_FloatRegister()) {
__ fld(reg->as_FloatRegister(), Address(t0, offset));
} else {
ShouldNotReachHere();
}
offset += 8;
}
}
Expand Down
Expand Up @@ -53,46 +53,22 @@ public class RISCV64Architecture implements Architecture {
// more fine-grained StorageClasses.
//
// Enumeration values of below two interfaces must consistent with riscv64 backend.
public interface RegTypes {
int INTEGER = 0;
int FLOAT = 1 << 8;
int STACK = 2 << 8;
}

// StorageClasses may look different from its counterpart in aarch64 and x86.
// Upper 16 bits is unused. Lower 16 bits is spilt 2 parts, the first part is regtype, the second part is width.
// regtype will determine what type of register will be allocated to the StorageClass, and width information will
// determine how riscv backend transfer data between memory and allocated register.
// | unused | RegType | width |
// 16 bits 8 bits 8 bits
public interface StorageClasses {
int INTEGER_8 = RegTypes.INTEGER | 8;
int INTEGER_16 = RegTypes.INTEGER | 16;
int INTEGER_32 = RegTypes.INTEGER | 32;
int INTEGER_64 = RegTypes.INTEGER | 64;
int FLOAT_32 = RegTypes.FLOAT | 32;
int FLOAT_64 = RegTypes.FLOAT | 64;
int STACK_SLOT = RegTypes.STACK;
int INTEGER = 0;
int FLOAT = 1;
int STACK = 2;

public static int fromTypeClass(TypeClass typeClass) {
return switch (typeClass) {
case INTEGER_8 -> INTEGER_8;
case INTEGER_16 -> INTEGER_16;
case INTEGER_32 -> INTEGER_32;
case INTEGER_64, POINTER -> INTEGER_64;
case FLOAT_64 -> FLOAT_64;
case FLOAT_32 -> FLOAT_32;
case INTEGER, POINTER -> INTEGER;
case FLOAT -> FLOAT;
default -> -1;
};
}

public static int toIntegerClass(int floatClass) {
assert floatClass == FLOAT_32 || floatClass == FLOAT_64;
return switch (floatClass) {
case FLOAT_32 -> INTEGER_32;
case FLOAT_64 -> INTEGER_64;
default -> -1;
};
assert floatClass == FLOAT;
return INTEGER;
}
}

Expand Down Expand Up @@ -164,36 +140,35 @@ public static int toIntegerClass(int floatClass) {
public static final VMStorage f31 = floatRegister(31, "ft11");

private static VMStorage integerRegister(int index, String debugName) {
return new VMStorage(RegTypes.INTEGER, index, debugName);
return new VMStorage(StorageClasses.INTEGER, index, debugName);
}

private static VMStorage floatRegister(int index, String debugName) {
return new VMStorage(RegTypes.FLOAT, index, debugName);
return new VMStorage(StorageClasses.FLOAT, index, debugName);
}

public static VMStorage stackStorage(int index) {
return new VMStorage(RegTypes.STACK, index, "Stack@" + index);
return new VMStorage(StorageClasses.STACK, index, "Stack@" + index);
}

@Override
public boolean isStackType(int cls) {
return cls == RegTypes.STACK;
return cls == StorageClasses.STACK;
}

@Override
public int typeSize(int cls) {
return switch (cls) {
case StorageClasses.INTEGER_8, StorageClasses.INTEGER_16,
StorageClasses.INTEGER_32, StorageClasses.INTEGER_64 -> INTEGER_REG_SIZE;
case StorageClasses.FLOAT_32, StorageClasses.FLOAT_64 -> FLOAT_REG_SIZE;
case StorageClasses.STACK_SLOT -> STACK_SLOT_SIZE;
case StorageClasses.INTEGER -> INTEGER_REG_SIZE;
case StorageClasses.FLOAT -> FLOAT_REG_SIZE;
case StorageClasses.STACK -> STACK_SLOT_SIZE;
default -> throw new IllegalArgumentException("Invalid type: " + cls);
};
}

@Override
public int stackType() {
return RegTypes.STACK;
return StorageClasses.STACK;
}

public static ABIDescriptor abiFor(VMStorage[] inputIntRegs, VMStorage[] inputFloatRegs, VMStorage[] outputIntRegs,
Expand Down
Expand Up @@ -60,32 +60,6 @@ public class LinuxRISCV64CallArranger {
x30 // ret buf addr reg
);

// Make registers as prototype, create vmstorages with same index with registers.
static Map.Entry<Integer, VMStorage[]> buildStorageEntry(int storageClass, VMStorage[][] storagePrototypes) {
VMStorage[] prototypes = storagePrototypes[storageClass >> 8];
VMStorage[] result = new VMStorage[prototypes.length];
for (int i = 0; i < prototypes.length; i++) {
result[i] = new VMStorage(storageClass, prototypes[i].index(), prototypes[i].name());
}
return Map.entry(storageClass, result);
}

// Code below will not declare new registers.
static final Map<Integer, VMStorage[]> inputStorage = Map.ofEntries(
buildStorageEntry(StorageClasses.INTEGER_8, CLinux.inputStorage),
buildStorageEntry(StorageClasses.INTEGER_16, CLinux.inputStorage),
buildStorageEntry(StorageClasses.INTEGER_32, CLinux.inputStorage),
buildStorageEntry(StorageClasses.INTEGER_64, CLinux.inputStorage),
buildStorageEntry(StorageClasses.FLOAT_32, CLinux.inputStorage),
buildStorageEntry(StorageClasses.FLOAT_64, CLinux.inputStorage)
);

static Map<Integer, VMStorage[]> outputStorage = inputStorage;

static int regType(int storageClass) {
return (storageClass >> 8) << 8;
}

public static class Bindings {
public final CallingSequence callingSequence;
public final boolean isInMemoryReturn;
Expand Down Expand Up @@ -174,14 +148,13 @@ VMStorage stackAlloc() {
}

Optional<VMStorage> regAlloc(int storageClass) {
int nRegsIdx = storageClass >> 8;
var availableRegs = MAX_REGISTER_ARGUMENTS - nRegs[nRegsIdx];
var availableRegs = MAX_REGISTER_ARGUMENTS - nRegs[storageClass];
if (availableRegs > 0) {
VMStorage[] source =
(forArguments ? inputStorage : outputStorage).get(storageClass);
(forArguments ? CLinux.inputStorage : CLinux.outputStorage)[storageClass];
Optional<VMStorage> result =
Optional.of(source[nRegs[nRegsIdx]]);
nRegs[nRegsIdx] += 1;
Optional.of(source[nRegs[storageClass]]);
nRegs[storageClass] += 1;
return result;
}
return Optional.empty();
Expand All @@ -191,9 +164,9 @@ Optional<VMStorage> regAlloc(int storageClass) {
VMStorage getStorage(int storageClass) {
Optional<VMStorage> storage = regAlloc(storageClass);
if (storage.isPresent()) return storage.get();
// If storageClass is RegTypes.FLOAT, and no floating-point register is available,
// If storageClass is StorageClasses.FLOAT, and no floating-point register is available,
// try to allocate an integer register.
if (regType(storageClass) == RegTypes.FLOAT) {
if (storageClass == StorageClasses.FLOAT) {
storage = regAlloc(StorageClasses.toIntegerClass(storageClass));
if (storage.isPresent()) return storage.get();
}
Expand All @@ -205,7 +178,7 @@ VMStorage[] getStorages(MemoryLayout layout) {
VMStorage[] storages = new VMStorage[regCnt];
for (int i = 0; i < regCnt; i++) {
// use integer calling convention.
storages[i] = getStorage(StorageClasses.INTEGER_64);
storages[i] = getStorage(StorageClasses.INTEGER);
}
return storages;
}
Expand Down Expand Up @@ -237,11 +210,9 @@ protected BindingCalculator(boolean forArguments) {

abstract List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, boolean isVariadicArg);

// Variadic arguments are passed according to the integer calling convention.
// When handling variadic part, integer calling convention should be used.
static final Map<TypeClass, TypeClass> conventionConverterMap =
Map.ofEntries(Map.entry(FLOAT_32, INTEGER_32),
Map.entry(FLOAT_64, INTEGER_64),
Map.ofEntries(Map.entry(FLOAT, INTEGER),
Map.entry(STRUCT_FA, STRUCT_A),
Map.entry(STRUCT_BOTH, STRUCT_A));
}
Expand All @@ -264,17 +235,16 @@ List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, boolean isVaria
}

List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, TypeClass argumentClass) {
// Binding.Builder will build a series of operation. Its working style like a stack interpreter.
Binding.Builder bindings = Binding.builder();
switch (argumentClass) {
case INTEGER_8, INTEGER_16, INTEGER_32, INTEGER_64, FLOAT_32, FLOAT_64 -> {
case INTEGER, FLOAT -> {
VMStorage storage = storageCalculator.getStorage(StorageClasses.fromTypeClass(argumentClass));
bindings.vmStore(storage, carrier);
}

case POINTER -> {
bindings.unboxAddress(carrier);
VMStorage storage = storageCalculator.getStorage(StorageClasses.INTEGER_64);
VMStorage storage = storageCalculator.getStorage(StorageClasses.INTEGER);
bindings.vmStore(storage, long.class);
}

Expand All @@ -287,7 +257,7 @@ List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, TypeClass argum
while (offset < layout.byteSize()) {
final long copy = Math.min(layout.byteSize() - offset, 8);
VMStorage storage = locations[locIndex++];
boolean useFloat = regType(storage.type()) == RegTypes.FLOAT;
boolean useFloat = storage.type() == StorageClasses.FLOAT;
Class<?> type = SharedUtils.primitiveCarrierForSize(copy, useFloat);
if (offset + copy < layout.byteSize()) {
bindings.dup();
Expand Down Expand Up @@ -340,7 +310,7 @@ List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, TypeClass argum
bindings.copy(layout)
.unboxAddress(MemorySegment.class);
VMStorage storage = storageCalculator.getStorage(
StorageClasses.INTEGER_64);
StorageClasses.INTEGER);
bindings.vmStore(storage, long.class);
}

Expand Down Expand Up @@ -368,13 +338,13 @@ List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, boolean isVaria
List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, TypeClass argumentClass) {
Binding.Builder bindings = Binding.builder();
switch (argumentClass) {
case INTEGER_8, INTEGER_16, INTEGER_32, INTEGER_64, FLOAT_32, FLOAT_64 -> {
case INTEGER, FLOAT -> {
VMStorage storage = storageCalculator.getStorage(StorageClasses.fromTypeClass(argumentClass));
bindings.vmLoad(storage, carrier);
}

case POINTER -> {
VMStorage storage = storageCalculator.getStorage(StorageClasses.INTEGER_64);
VMStorage storage = storageCalculator.getStorage(StorageClasses.INTEGER);
bindings.vmLoad(storage, long.class)
.boxAddress();
}
Expand All @@ -389,7 +359,7 @@ List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, TypeClass argum
while (offset < layout.byteSize()) {
final long copy = Math.min(layout.byteSize() - offset, 8);
VMStorage storage = locations[locIndex++];
boolean useFloat = regType(storage.type()) == RegTypes.FLOAT;
boolean useFloat = storage.type() == StorageClasses.FLOAT;
Class<?> type = SharedUtils.primitiveCarrierForSize(copy, useFloat);
bindings.dup().vmLoad(storage, type)
.bufferStore(offset, type);
Expand Down Expand Up @@ -437,7 +407,7 @@ List<Binding> getBindings(Class<?> carrier, MemoryLayout layout, TypeClass argum
case STRUCT_REFERENCE -> {
assert carrier == MemorySegment.class;
VMStorage storage = storageCalculator.getStorage(
StorageClasses.INTEGER_64);
StorageClasses.INTEGER);
bindings.vmLoad(storage, long.class)
.boxAddress()
.toSegment(layout);
Expand Down

0 comments on commit d5e2448

Please sign in to comment.