Skip to content

Commit

Permalink
8296477: Foreign linker implementation update following JEP 434
Browse files Browse the repository at this point in the history
Co-authored-by: Jorn Vernee <jvernee@openjdk.org>
Co-authored-by: Nick Gasson <ngasson@openjdk.org>
Co-authored-by: Per Minborg <pminborg@openjdk.org>
Reviewed-by: rehn, mcimadamore, vlivanov
  • Loading branch information
3 people committed Dec 5, 2022
1 parent 73baadc commit 0452c39
Show file tree
Hide file tree
Showing 72 changed files with 2,586 additions and 935 deletions.
125 changes: 76 additions & 49 deletions src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,25 @@ class DowncallStubGenerator : public StubCodeGenerator {
BasicType _ret_bt;
const ABIDescriptor& _abi;

const GrowableArray<VMReg>& _input_registers;
const GrowableArray<VMReg>& _output_registers;
const GrowableArray<VMStorage>& _input_registers;
const GrowableArray<VMStorage>& _output_registers;

bool _needs_return_buffer;
int _captured_state_mask;

int _frame_complete;
int _framesize;
int _frame_size_slots;
OopMapSet* _oop_maps;
public:
DowncallStubGenerator(CodeBuffer* buffer,
BasicType* signature,
int num_args,
BasicType ret_bt,
const ABIDescriptor& abi,
const GrowableArray<VMReg>& input_registers,
const GrowableArray<VMReg>& output_registers,
bool needs_return_buffer)
const GrowableArray<VMStorage>& input_registers,
const GrowableArray<VMStorage>& output_registers,
bool needs_return_buffer,
int captured_state_mask)
: StubCodeGenerator(buffer, PrintMethodHandleStubs),
_signature(signature),
_num_args(num_args),
Expand All @@ -67,8 +69,9 @@ class DowncallStubGenerator : public StubCodeGenerator {
_input_registers(input_registers),
_output_registers(output_registers),
_needs_return_buffer(needs_return_buffer),
_captured_state_mask(captured_state_mask),
_frame_complete(0),
_framesize(0),
_frame_size_slots(0),
_oop_maps(NULL) {
}

Expand All @@ -79,7 +82,7 @@ class DowncallStubGenerator : public StubCodeGenerator {
}

int framesize() const {
return (_framesize >> (LogBytesPerWord - LogBytesPerInt));
return (_frame_size_slots >> (LogBytesPerWord - LogBytesPerInt));
}

OopMapSet* oop_maps() const {
Expand All @@ -93,12 +96,15 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature,
int num_args,
BasicType ret_bt,
const ABIDescriptor& abi,
const GrowableArray<VMReg>& input_registers,
const GrowableArray<VMReg>& output_registers,
bool needs_return_buffer) {
int locs_size = 64;
const GrowableArray<VMStorage>& input_registers,
const GrowableArray<VMStorage>& output_registers,
bool needs_return_buffer,
int captured_state_mask) {
int locs_size = 64;
CodeBuffer code("nep_invoker_blob", native_invoker_code_size, locs_size);
DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, input_registers, output_registers, needs_return_buffer);
DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi,
input_registers, output_registers,
needs_return_buffer, captured_state_mask);
g.generate();
code.log_section_sizes("nep_invoker_blob");

Expand Down Expand Up @@ -137,10 +143,10 @@ void DowncallStubGenerator::generate() {
Register tmp1 = r9;
Register tmp2 = r10;

Register shuffle_reg = r19;
VMStorage shuffle_reg = as_VMStorage(r19);
JavaCallingConvention in_conv;
NativeCallingConvention out_conv(_input_registers);
ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg->as_VMReg());
ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg);

#ifndef PRODUCT
LogTarget(Trace, foreign, downcall) lt;
Expand All @@ -152,46 +158,50 @@ void DowncallStubGenerator::generate() {
#endif

int allocated_frame_size = 0;
if (_needs_return_buffer) {
allocated_frame_size += 8; // for address spill
}
allocated_frame_size += arg_shuffle.out_arg_stack_slots() <<LogBytesPerInt;
assert(_abi._shadow_space_bytes == 0, "not expecting shadow space on AArch64");
allocated_frame_size += arg_shuffle.out_arg_bytes();

int ret_buf_addr_sp_offset = -1;
if (_needs_return_buffer) {
// in sync with the above
ret_buf_addr_sp_offset = allocated_frame_size - 8;
}

bool should_save_return_value = !_needs_return_buffer;
RegSpiller out_reg_spiller(_output_registers);
int spill_offset = -1;

if (!_needs_return_buffer) {
if (should_save_return_value) {
spill_offset = 0;
// spill area can be shared with the above, so we take the max of the 2
// spill area can be shared with shadow space and out args,
// since they are only used before the call,
// and spill area is only used after.
allocated_frame_size = out_reg_spiller.spill_size_bytes() > allocated_frame_size
? out_reg_spiller.spill_size_bytes()
: allocated_frame_size;
}

_framesize = align_up(framesize
+ (allocated_frame_size >> LogBytesPerInt), 4);
assert(is_even(_framesize/2), "sp not 16-byte aligned");
StubLocations locs;
locs.set(StubLocations::TARGET_ADDRESS, _abi._scratch1);
if (_needs_return_buffer) {
locs.set_frame_data(StubLocations::RETURN_BUFFER, allocated_frame_size);
allocated_frame_size += BytesPerWord; // for address spill
}
if (_captured_state_mask != 0) {
locs.set_frame_data(StubLocations::CAPTURED_STATE_BUFFER, allocated_frame_size);
allocated_frame_size += BytesPerWord;
}

_frame_size_slots = align_up(framesize + (allocated_frame_size >> LogBytesPerInt), 4);
assert(is_even(_frame_size_slots/2), "sp not 16-byte aligned");

_oop_maps = new OopMapSet();
address start = __ pc();

__ enter();

// lr and fp are already in place
__ sub(sp, rfp, ((unsigned)_framesize-4) << LogBytesPerInt); // prolog
__ sub(sp, rfp, ((unsigned)_frame_size_slots-4) << LogBytesPerInt); // prolog

_frame_complete = __ pc() - start;

address the_pc = __ pc();
__ set_last_Java_frame(sp, rfp, the_pc, tmp1);
OopMap* map = new OopMap(_framesize, 0);
OopMap* map = new OopMap(_frame_size_slots, 0);
_oop_maps->add_gc_map(the_pc - start, map);

// State transition
Expand All @@ -200,34 +210,51 @@ void DowncallStubGenerator::generate() {
__ stlrw(tmp1, tmp2);

__ block_comment("{ argument shuffle");
arg_shuffle.generate(_masm, shuffle_reg->as_VMReg(), 0, _abi._shadow_space_bytes);
if (_needs_return_buffer) {
assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill");
__ str(_abi._ret_buf_addr_reg, Address(sp, ret_buf_addr_sp_offset));
}
arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes, locs);
__ block_comment("} argument shuffle");

__ blr(_abi._target_addr_reg);
__ blr(as_Register(locs.get(StubLocations::TARGET_ADDRESS)));
// this call is assumed not to have killed rthread

if (_needs_return_buffer) {
assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill");
__ ldr(tmp1, Address(sp, ret_buf_addr_sp_offset));
__ ldr(tmp1, Address(sp, locs.data_offset(StubLocations::RETURN_BUFFER)));
int offset = 0;
for (int i = 0; i < _output_registers.length(); i++) {
VMReg reg = _output_registers.at(i);
if (reg->is_Register()) {
__ str(reg->as_Register(), Address(tmp1, offset));
VMStorage reg = _output_registers.at(i);
if (reg.type() == StorageType::INTEGER) {
__ str(as_Register(reg), Address(tmp1, offset));
offset += 8;
} else if(reg->is_FloatRegister()) {
__ strd(reg->as_FloatRegister(), Address(tmp1, offset));
} else if (reg.type() == StorageType::VECTOR) {
__ strd(as_FloatRegister(reg), Address(tmp1, offset));
offset += 16;
} else {
ShouldNotReachHere();
}
}
}

//////////////////////////////////////////////////////////////////////////////

if (_captured_state_mask != 0) {
__ block_comment("{ save thread local");

if (should_save_return_value) {
out_reg_spiller.generate_spill(_masm, spill_offset);
}

__ ldr(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER)));
__ movw(c_rarg1, _captured_state_mask);
__ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state), tmp1);

if (should_save_return_value) {
out_reg_spiller.generate_fill(_masm, spill_offset);
}

__ block_comment("} save thread local");
}

//////////////////////////////////////////////////////////////////////////////

__ mov(tmp1, _thread_in_native_trans);
__ strw(tmp1, Address(rthread, JavaThread::thread_state_offset()));

Expand Down Expand Up @@ -272,7 +299,7 @@ void DowncallStubGenerator::generate() {
__ block_comment("{ L_safepoint_poll_slow_path");
__ bind(L_safepoint_poll_slow_path);

if (!_needs_return_buffer) {
if (should_save_return_value) {
// Need to save the native result registers around any runtime calls.
out_reg_spiller.generate_spill(_masm, spill_offset);
}
Expand All @@ -282,7 +309,7 @@ void DowncallStubGenerator::generate() {
__ lea(tmp1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
__ blr(tmp1);

if (!_needs_return_buffer) {
if (should_save_return_value) {
out_reg_spiller.generate_fill(_masm, spill_offset);
}

Expand All @@ -294,13 +321,13 @@ void DowncallStubGenerator::generate() {
__ block_comment("{ L_reguard");
__ bind(L_reguard);

if (!_needs_return_buffer) {
if (should_save_return_value) {
out_reg_spiller.generate_spill(_masm, spill_offset);
}

__ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), tmp1);

if (!_needs_return_buffer) {
if (should_save_return_value) {
out_reg_spiller.generate_fill(_masm, spill_offset);
}

Expand Down

1 comment on commit 0452c39

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.