Skip to content

Commit

Permalink
8343430: RISC-V: C2: Remove old trampoline call
Browse files Browse the repository at this point in the history
Reviewed-by: mli, rehn
  • Loading branch information
RealFYang committed Nov 13, 2024
1 parent b26e495 commit eb40a88
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 623 deletions.
2 changes: 1 addition & 1 deletion src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
relocInfo::static_call_type);
address call = __ reloc_call(resolve);
if (call == nullptr) {
ce->bailout("trampoline stub overflow");
ce->bailout("reloc call address stub overflow");
return;
}
ce->add_call_info_here(info());
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1346,7 +1346,7 @@ void LIR_Assembler::align_call(LIR_Code code) {
void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
address call = __ reloc_call(Address(op->addr(), rtype));
if (call == nullptr) {
bailout("trampoline stub overflow");
bailout("reloc call address stub overflow");
return;
}
add_call_info(code_offset(), op->info());
Expand All @@ -1356,7 +1356,7 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
address call = __ ic_call(op->addr());
if (call == nullptr) {
bailout("trampoline stub overflow");
bailout("reloc call address stub overflow");
return;
}
add_call_info(code_offset(), op->info());
Expand Down
8 changes: 4 additions & 4 deletions src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ friend class ArrayCopyStub;
void deoptimize_trap(CodeEmitInfo *info);

enum {
// See emit_static_call_stub for detail
// CompiledDirectCall::to_interp_stub_size() (14) + CompiledDirectCall::to_trampoline_stub_size() (1 + 3 + address)
_call_stub_size = 14 * MacroAssembler::instruction_size +
(MacroAssembler::instruction_size + MacroAssembler::NativeShortCall::trampoline_size),
// call stub: CompiledDirectCall::to_interp_stub_size() +
// CompiledDirectCall::to_trampoline_stub_size()
_call_stub_size = 11 * MacroAssembler::instruction_size +
1 * MacroAssembler::instruction_size + wordSize,
// See emit_exception_handler for detail
// verify_not_null_oop + far_call + should_not_reach_here + invalidate_registers(DEBUG_ONLY)
_exception_handler_size = DEBUG_ONLY(584) NOT_DEBUG(548), // or smaller
Expand Down
57 changes: 1 addition & 56 deletions src/hotspot/cpu/riscv/codeBuffer_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,61 +28,6 @@
#include "asm/codeBuffer.inline.hpp"
#include "asm/macroAssembler.hpp"

void CodeBuffer::share_trampoline_for(address dest, int caller_offset) {
if (_shared_trampoline_requests == nullptr) {
constexpr unsigned init_size = 8;
constexpr unsigned max_size = 256;
_shared_trampoline_requests = new (mtCompiler)SharedTrampolineRequests(init_size, max_size);
}

bool created;
Offsets* offsets = _shared_trampoline_requests->put_if_absent(dest, &created);
if (created) {
_shared_trampoline_requests->maybe_grow();
}
offsets->add(caller_offset);
_finalize_stubs = true;
}

#define __ masm.

static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampolineRequests* requests) {
if (requests == nullptr) {
return true;
}
assert(UseTrampolines, "We are not using trampolines");

MacroAssembler masm(cb);

auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) {
assert(cb->stubs()->remaining() >= MacroAssembler::max_reloc_call_stub_size(), "pre-allocated trampolines");
LinkedListIterator<int> it(offsets.head());
int offset = *it.next();
address stub = __ emit_trampoline_stub(offset, dest);
assert(stub, "pre-allocated trampolines");

address reloc_pc = cb->stubs()->end() - MacroAssembler::NativeShortCall::trampoline_size;
while (!it.is_empty()) {
offset = *it.next();
address caller_pc = cb->insts()->start() + offset;
cb->stubs()->relocate(reloc_pc, trampoline_stub_Relocation::spec(caller_pc));
}
return true;
};

assert(requests->number_of_entries() >= 1, "at least one");
const int total_requested_size = MacroAssembler::max_reloc_call_stub_size() * requests->number_of_entries();
if (cb->stubs()->maybe_expand_to_ensure_remaining(total_requested_size) && cb->blob() == nullptr) {
return false;
}

requests->iterate(emit);
return true;
}

#undef __

bool CodeBuffer::pd_finalize_stubs() {
return emit_shared_stubs_to_interp<MacroAssembler>(this, _shared_stub_to_interp_requests)
&& emit_shared_trampolines(this, _shared_trampoline_requests);
return emit_shared_stubs_to_interp<MacroAssembler>(this, _shared_stub_to_interp_requests);
}
4 changes: 1 addition & 3 deletions src/hotspot/cpu/riscv/codeBuffer_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@

public:
void flush_bundle(bool start_new_bundle) {}
static bool supports_shared_stubs() { return UseTrampolines; }

void share_trampoline_for(address dest, int caller_offset);
static bool supports_shared_stubs() { return false; }

#endif // CPU_RISCV_CODEBUFFER_RISCV_HPP
6 changes: 3 additions & 3 deletions src/hotspot/cpu/riscv/compiledIC_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ int CompiledDirectCall::to_interp_stub_size() {
}

int CompiledDirectCall::to_trampoline_stub_size() {
// We count instructions and an additional alignment nop.
// Trampoline stubs are always word aligned.
return MacroAssembler::max_reloc_call_stub_size();
// We count size of target address and an additional alignment nop.
// Reloc call address stubs are always word aligned.
return MacroAssembler::max_reloc_call_address_stub_size();
}

// Relocation entries for call stub, compiled java to interpreter.
Expand Down
2 changes: 0 additions & 2 deletions src/hotspot/cpu/riscv/globals_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ define_pd_global(intx, InlineSmallCode, 1000);
"Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \
product(bool, UseRVVForBigIntegerShiftIntrinsics, true, \
"Use RVV instructions for left/right shift of BigInteger") \
product(bool, UseTrampolines, false, EXPERIMENTAL, \
"Far calls uses jal to trampoline.") \
product(bool, UseCtxFencei, false, EXPERIMENTAL, \
"Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush")

Expand Down
149 changes: 25 additions & 124 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -967,26 +967,6 @@ void MacroAssembler::li(Register Rd, int64_t imm) {
}
}

void MacroAssembler::load_link_jump(const address source, Register temp) {
assert(temp != noreg && temp != x0, "expecting a register");
assert(temp != x5, "temp register must not be x5.");
assert_cond(source != nullptr);
int64_t distance = source - pc();
assert(is_simm32(distance), "Must be");
auipc(temp, (int32_t)distance + 0x800);
ld(temp, Address(temp, ((int32_t)distance << 20) >> 20));
jalr(temp);
}

void MacroAssembler::jump_link(const address dest, Register temp) {
assert(UseTrampolines, "Must be");
assert_cond(dest != nullptr);
int64_t distance = dest - pc();
assert(is_simm21(distance), "Must be");
assert((distance % 2) == 0, "Must be");
jal(x1, distance);
}

void MacroAssembler::j(const address dest, Register temp) {
assert(CodeCache::contains(dest), "Must be");
assert_cond(dest != nullptr);
Expand Down Expand Up @@ -4282,55 +4262,16 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) {
zero_extend(dst, dst, 32);
}

// Maybe emit a call via a trampoline. If the code cache is small
// trampolines won't be emitted.
address MacroAssembler::trampoline_call(Address entry) {
address MacroAssembler::reloc_call(Address entry, Register tmp) {
assert(entry.rspec().type() == relocInfo::runtime_call_type ||
entry.rspec().type() == relocInfo::opt_virtual_call_type ||
entry.rspec().type() == relocInfo::static_call_type ||
entry.rspec().type() == relocInfo::virtual_call_type, "wrong reloc type");

address target = entry.target();

// We need a trampoline if branches are far.
if (!in_scratch_emit_size()) {
if (entry.rspec().type() == relocInfo::runtime_call_type) {
assert(CodeBuffer::supports_shared_stubs(), "must support shared stubs");
code()->share_trampoline_for(entry.target(), offset());
} else {
address stub = emit_trampoline_stub(offset(), target);
if (stub == nullptr) {
postcond(pc() == badAddress);
return nullptr; // CodeCache is full
}
}
}
target = pc();

address call_pc = pc();
#ifdef ASSERT
if (entry.rspec().type() != relocInfo::runtime_call_type) {
assert_alignment(call_pc);
}
#endif
relocate(entry.rspec(), [&] {
jump_link(target, t0);
});

postcond(pc() != badAddress);
return call_pc;
}

address MacroAssembler::load_and_call(Address entry) {
assert(entry.rspec().type() == relocInfo::runtime_call_type ||
entry.rspec().type() == relocInfo::opt_virtual_call_type ||
entry.rspec().type() == relocInfo::static_call_type ||
entry.rspec().type() == relocInfo::virtual_call_type, "wrong reloc type");

address target = entry.target();

if (!in_scratch_emit_size()) {
address stub = emit_address_stub(offset(), target);
address stub = emit_reloc_call_address_stub(offset(), target);
if (stub == nullptr) {
postcond(pc() == badAddress);
return nullptr; // CodeCache is full
Expand All @@ -4343,8 +4284,13 @@ address MacroAssembler::load_and_call(Address entry) {
assert_alignment(call_pc);
}
#endif

// The relocation created while emitting the stub will ensure this
// call instruction is subsequently patched to call the stub.
relocate(entry.rspec(), [&] {
load_link_jump(target, t1);
auipc(tmp, 0);
ld(tmp, Address(tmp, 0));
jalr(tmp);
});

postcond(pc() != badAddress);
Expand Down Expand Up @@ -4404,95 +4350,50 @@ int MacroAssembler::ic_check(int end_alignment) {
return uep_offset;
}

address MacroAssembler::emit_address_stub(int insts_call_instruction_offset, address dest) {
address stub = start_a_stub(max_reloc_call_stub_size());
if (stub == nullptr) {
return nullptr; // CodeBuffer::expand failed
}

// We are always 4-byte aligned here.
assert_alignment(pc());

// Make sure the address of destination 8-byte aligned.
align(wordSize, 0);

RelocationHolder rh = trampoline_stub_Relocation::spec(code()->insts()->start() +
insts_call_instruction_offset);
const int stub_start_offset = offset();
relocate(rh, [&] {
assert(offset() - stub_start_offset == 0,
"%ld - %ld == %ld : should be", (long)offset(), (long)stub_start_offset, (long)0);
assert(offset() % wordSize == 0, "bad alignment");
emit_int64((int64_t)dest);
});

const address stub_start_addr = addr_at(stub_start_offset);
end_a_stub();

return stub_start_addr;
}

// Emit a trampoline stub for a call to a target which is too far away.
// Emit an address stub for a call to a target which is too far away.
// Note that we only put the target address of the call in the stub.
//
// code sequences:
//
// call-site:
// branch-and-link to <destination> or <trampoline stub>
// load target address from stub
// jump-and-link target address
//
// Related trampoline stub for this call site in the stub section:
// load the call target from the constant pool
// branch (RA still points to the call site above)

address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
address dest) {
// Max stub size: alignment nop, TrampolineStub.
address stub = start_a_stub(max_reloc_call_stub_size());
// Related address stub for this call site in the stub section:
// alignment nop
// target address

address MacroAssembler::emit_reloc_call_address_stub(int insts_call_instruction_offset, address dest) {
address stub = start_a_stub(max_reloc_call_address_stub_size());
if (stub == nullptr) {
return nullptr; // CodeBuffer::expand failed
}

assert(UseTrampolines, "Must be using trampos.");

// We are always 4-byte aligned here.
assert_alignment(pc());

// Create a trampoline stub relocation which relates this trampoline stub
// with the call instruction at insts_call_instruction_offset in the
// instructions code-section.

// Make sure the address of destination 8-byte aligned after 3 instructions.
align(wordSize, MacroAssembler::NativeShortCall::trampoline_data_offset);
// Make sure the address of destination 8-byte aligned.
align(wordSize, 0);

RelocationHolder rh = trampoline_stub_Relocation::spec(code()->insts()->start() +
insts_call_instruction_offset);
const int stub_start_offset = offset();
relocate(rh, [&] {
// Now, create the trampoline stub's code:
// - load the call
// - call
Label target;
ld(t1, target); // auipc + ld
jr(t1); // jalr
bind(target);
assert(offset() - stub_start_offset == MacroAssembler::NativeShortCall::trampoline_data_offset,
"should be");
assert(offset() - stub_start_offset == 0,
"%ld - %ld == %ld : should be", (long)offset(), (long)stub_start_offset, (long)0);
assert(offset() % wordSize == 0, "bad alignment");
emit_int64((int64_t)dest);
});

const address stub_start_addr = addr_at(stub_start_offset);

end_a_stub();

return stub_start_addr;
}

int MacroAssembler::max_reloc_call_stub_size() {
// Max stub size: alignment nop, TrampolineStub.
if (UseTrampolines) {
return instruction_size + MacroAssembler::NativeShortCall::trampoline_size;
}
return instruction_size + wordSize;
int MacroAssembler::max_reloc_call_address_stub_size() {
// Max stub size: alignment nop, target address.
return 1 * instruction_size + wordSize;
}

int MacroAssembler::static_call_stub_size() {
Expand Down
Loading

0 comments on commit eb40a88

Please sign in to comment.