Skip to content

Commit

Permalink
Use CP for addr
Browse files Browse the repository at this point in the history
  • Loading branch information
robehn committed Jun 13, 2024
1 parent bb7249b commit 02a3db3
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 104 deletions.
67 changes: 41 additions & 26 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3727,52 +3727,67 @@ 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::patchable_far_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();

address MacroAssembler::patchable_far_call_trampoline(Address entry) {
if (!in_scratch_emit_size()) {
if (entry.rspec().type() == relocInfo::runtime_call_type && UseTrampolines) {
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 = nullptr;
if (UseTrampolines) {
// We need a trampoline if branches are far.
stub = emit_trampoline_stub(offset(), target);
} else {
stub = emit_address_stub(offset(), target);
}
// We need a trampoline if branches are far.
address stub = emit_trampoline_stub(offset(), entry.target());
if (stub == nullptr) {
postcond(pc() == badAddress);
return nullptr; // CodeCache is full
}
}
}
target = pc();

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

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

address MacroAssembler::patchable_far_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");

if (UseTrampolines) {
return patchable_far_call_trampoline(entry);
}

address target = entry.target();
address addr_to_cp_entry = nullptr;

if (!in_scratch_emit_size()) {
addr_to_cp_entry = address_constant(target);
if (addr_to_cp_entry == nullptr) {
return nullptr; // CodeCache is full
}

RelocationHolder rh = section_word_Relocation::spec(addr_to_cp_entry, CodeBuffer::SECT_CONSTS);
relocate(rh);
} else {
addr_to_cp_entry = pc();
}

address call_at = pc();
relocate(entry.rspec(), [&] {
load_link(addr_to_cp_entry, t0);
});

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

address MacroAssembler::ic_call(address entry, jint method_index) {
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,9 @@ class MacroAssembler: public Assembler {
//
// Return: the call PC or null if CodeCache is full.
address patchable_far_call(Address entry);
private:
address patchable_far_call_trampoline(Address entry);
public:

address ic_call(address entry, jint method_index = 0);
static int ic_check_size();
Expand Down
113 changes: 38 additions & 75 deletions src/hotspot/cpu/riscv/nativeInst_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,15 +348,6 @@ class NativeFarCall: public NativeInstruction {
bool set_destination_mt_safe(address dest, bool assert_lock = true);
bool reloc_set_destination(address dest);

private:
address stub_address();
address stub_address_destination();
bool has_address_stub();

static void set_stub_address_destination_at(address dest, address value);
static address stub_address_destination_at(address src);
public:

static NativeFarCall* at(address addr);
static bool is_at(address addr);
static bool is_call_before(address return_address);
Expand All @@ -366,30 +357,24 @@ class NativeFarCall: public NativeInstruction {

address NativeFarCall::destination() const {
address addr = addr_at(0);
assert(NativeFarCall::is_at(addr), "unexpected code at call site");

address destination = MacroAssembler::target_addr_for_insn(addr);

CodeBlob* cb = CodeCache::find_blob(addr);
assert(cb && cb->is_nmethod(), "sanity");
nmethod *nm = (nmethod *)cb;
assert(nm != nullptr, "Sanity");
assert(nm->stub_contains(destination), "Sanity");
assert(destination != nullptr, "Sanity");
return stub_address_destination_at(destination);
address dest_addr = MacroAssembler::target_addr_for_insn(addr);
address dest = (address)get_data64_at(dest_addr);
return dest;
}

address NativeFarCall::reloc_destination(address orig_address) {
address call_addr = addr_at(0);
address new_addr = addr_at(0);

CodeBlob *code = CodeCache::find_blob(call_addr);
assert(code != nullptr, "Could not find the containing code blob");
address stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code);

if (stub_addr != nullptr) {
stub_addr = MacroAssembler::target_addr_for_insn(call_addr);
if (orig_address != nullptr) {
assert(NativeFarCall::is_at(orig_address), "unexpected code at call site");
address old_cp_dest = MacroAssembler::target_addr_for_insn(orig_address);
address old_dest = (address)get_data64_at(old_cp_dest);
return old_dest;
} else {
address new_cp_dest = MacroAssembler::target_addr_for_insn(new_addr);
address new_dest = (address)get_data64_at(new_cp_dest);
return new_dest;
}
return stub_addr;
}

void NativeFarCall::set_destination(address dest) {
Expand All @@ -415,65 +400,43 @@ bool NativeFarCall::set_destination_mt_safe(address dest, bool assert_lock) {
"concurrent code patching");

address call_addr = addr_at(0);
assert(NativeFarCall::is_at(call_addr), "unexpected code at call site");

address stub_addr = stub_address();

if (stub_addr != nullptr) {
set_stub_address_destination_at(stub_addr, dest);
return true;
}
address cp_pool_addr = MacroAssembler::target_addr_for_insn(call_addr);

return false;
assert(cp_pool_addr != nullptr, "Must be");
set_data64_at(cp_pool_addr, (uint64_t)dest);
OrderAccess::release();
return true;
}

bool NativeFarCall::reloc_set_destination(address dest) {
address call_addr = addr_at(0);
assert(NativeFarCall::is_at(call_addr), "unexpected code at call site");

CodeBlob *code = CodeCache::find_blob(call_addr);
assert(code != nullptr, "Could not find the containing code blob");
address stub_addr = trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code);
CodeBlob* cb = CodeCache::find_blob(call_addr);
assert(cb != nullptr, "Could not find code blob");
nmethod* nm = cb->as_nmethod_or_null();

if (stub_addr != nullptr) {
MacroAssembler::pd_patch_instruction_size(call_addr, stub_addr);
address cp_entry_addr = nullptr;
if (nm != nullptr) {
RelocIterator iter(nm, instruction_address(), next_instruction_address());
while (iter.next()) {
if (iter.type() == relocInfo::section_word_type) {
cp_entry_addr = iter.section_word_reloc()->target();
break;
}
}
}

return true;
}

void NativeFarCall::set_stub_address_destination_at(address dest, address value) {
assert_cond(dest != nullptr);
assert_cond(value != nullptr);

set_data64_at(dest, (uint64_t)value);
OrderAccess::release();
}

address NativeFarCall::stub_address_destination_at(address src) {
assert_cond(src != nullptr);
address dest = (address)get_data64_at(src);
return dest;
}

address NativeFarCall::stub_address() {
address call_addr = addr_at(0);

CodeBlob *code = CodeCache::find_blob(call_addr);
assert(code != nullptr, "Could not find the containing code blob");

address dest = MacroAssembler::pd_call_destination(call_addr);
assert(code->contains(dest), "Sanity");
return dest;
if (cp_entry_addr != nullptr) {
MacroAssembler::pd_patch_instruction_size(call_addr, cp_entry_addr);
} else {
cp_entry_addr = MacroAssembler::target_addr_for_insn(call_addr);
}

}
assert(MacroAssembler::target_addr_for_insn(call_addr) == cp_entry_addr, "Must be");

bool NativeFarCall::has_address_stub() {
return stub_address() != nullptr;
}
set_data64_at(cp_entry_addr, (uint64_t)dest);

address NativeFarCall::stub_address_destination() {
return stub_address_destination_at(stub_address());
return true;
}

NativeFarCall* NativeFarCall::at(address addr) {
Expand Down
9 changes: 8 additions & 1 deletion src/hotspot/share/code/compiledIC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,11 @@ CompiledIC* CompiledIC_before(nmethod* nm, address return_addr) {

CompiledIC* CompiledIC_at(nmethod* nm, address call_site) {
RelocIterator iter(nm, call_site, call_site + 1);
iter.next();
while (iter.next()) {
if (iter.reloc()->type() == relocInfo::virtual_call_type) {
break;
}
}
return CompiledIC_at(&iter);
}

Expand Down Expand Up @@ -402,7 +406,10 @@ address CompiledDirectCall::find_stub_for(address instruction) {
// from the CompiledIC implementation
case relocInfo::opt_virtual_call_type:
return iter.opt_virtual_call_reloc()->static_stub();
case relocInfo::section_word_type:
break;
default:
assert(false, "Type: %d", iter.type());
ShouldNotReachHere();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/runtime/sharedRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2742,14 +2742,14 @@ void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) {
struct { double data[20]; } locs_buf;
struct { double data[20]; } stubs_locs_buf;
buffer.insts()->initialize_shared_locs((relocInfo*)&locs_buf, sizeof(locs_buf) / sizeof(relocInfo));
#if defined(AARCH64) || defined(PPC64)
#if defined(AARCH64) || defined(PPC64) || defined(RISCV)
// On AArch64 with ZGC and nmethod entry barriers, we need all oops to be
// in the constant pool to ensure ordering between the barrier and oops
// accesses. For native_wrappers we need a constant.
// On PPC64 the continuation enter intrinsic needs the constant pool for the compiled
// static java call that is resolved in the runtime.
if (PPC64_ONLY(method->is_continuation_enter_intrinsic() &&) true) {
buffer.initialize_consts_size(8 PPC64_ONLY(+ 24));
buffer.initialize_consts_size(8 PPC64_ONLY(+ 24) RISCV_ONLY(+ 8));
}
#endif
buffer.stubs()->initialize_shared_locs((relocInfo*)&stubs_locs_buf, sizeof(stubs_locs_buf) / sizeof(relocInfo));
Expand Down

0 comments on commit 02a3db3

Please sign in to comment.