Skip to content

Commit

Permalink
Second relocator
Browse files Browse the repository at this point in the history
  • Loading branch information
robehn committed Jun 13, 2024
1 parent eb30360 commit c29aa53
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 130 deletions.
96 changes: 65 additions & 31 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@
#define STOP(str) stop(str);
#define BIND(label) bind(label); __ BLOCK_COMMENT(#label ":")



Register MacroAssembler::extract_rs1(address instr) {
assert_cond(instr != nullptr);
return as_Register(Assembler::extract(Assembler::ld_instr(instr), 19, 15));
Expand Down Expand Up @@ -978,11 +976,11 @@ void MacroAssembler::li(Register Rd, int64_t imm) {
}
}

void MacroAssembler::load_link(const address source, Register temp) {
void MacroAssembler::load_link(const address target, Register temp) {
assert(temp != noreg && temp != x0, "expecting a register");
assert(temp == x5, "expecting a register");
assert_cond(source != nullptr);
int64_t distance = source - pc();
assert_cond(target != nullptr);
int64_t distance = target - pc();
assert(is_simm32(distance), "Must be");
Assembler::auipc(temp, (int32_t)distance + 0x800);
Assembler::_ld(temp, temp, ((int32_t)distance << 20) >> 20);
Expand Down Expand Up @@ -1739,6 +1737,13 @@ address MacroAssembler::target_addr_for_insn(address insn_addr) {
} else if (MacroAssembler::is_li32_at(insn_addr)) { // li32
return get_target_of_li32(insn_addr);
} else {
/*CodeBlob* cb = CodeCache::find_blob(insn_addr);
if (insn_addr >= new_cb->content_begin() &&
insn_addr < new_cb->content_end()) {
address ret = get_data64_at(insn_addr);
fprintf(stderr,"CALL (%s) CP AT: %p contains: %p\n", __func__, insn_addr, ); fflush(stderr);
return (address)get_data64_at(insn_addr);
}*/
ShouldNotReachHere();
}
return address(((uintptr_t)insn_addr + offset));
Expand Down Expand Up @@ -3727,53 +3732,82 @@ 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;
}

// 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");

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);
});

fprintf(stderr, "CALL (%s) %s AT: %p loads: %p contains: %p\n", __func__, in_scratch_emit_size() ? "SCRATCH" : "REAL" , call_at, addr_to_cp_entry, target); fflush(stderr);

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



/*
RelocationHolder rh = entry.rspec();
((CallRelocation*)rh.reloc())->set_constant_pool_offset(cp_off);
int offset_cp = ((CallRelocation*)rh.reloc())->get_constant_pool_offset();
assert(offset_cp == cp_off, "Must be: %d == %d", offset_cp, cp_off);
*/

address MacroAssembler::ic_call(address entry, jint method_index) {
RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index);
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,7 @@ class MacroAssembler: public Assembler {
//
// Return: the call PC or null if CodeCache is full.
address patchable_far_call(Address entry);
address patchable_far_call_trampoline(Address entry);

address ic_call(address entry, jint method_index = 0);
static int ic_check_size();
Expand Down
151 changes: 71 additions & 80 deletions src/hotspot/cpu/riscv/nativeInst_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ bool NativeShortCall::set_destination_mt_safe(address dest, bool assert_lock) {
bool NativeShortCall::reloc_set_destination(address dest) {
address call_addr = addr_at(0);
assert(NativeCall::is_at(call_addr), "unexpected code at call site");

// Patch the constant in the call's trampoline stub.
address trampoline_stub_addr = get_trampoline();
if (trampoline_stub_addr != nullptr) {
Expand Down Expand Up @@ -338,24 +338,15 @@ class NativeFarCall: public NativeInstruction {
address next_instruction_address() const { return addr_at(return_address_offset); }
address return_address() const { return addr_at(return_address_offset); }
address destination() const;
address reloc_destination(address orig_address);
address reloc_destination(address orig_address, int cp_offset);

void set_destination(address dest);
void verify_alignment() {} // do nothing on riscv
void verify();
void print();

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:
bool reloc_set_destination(address dest, int cp_offset);

static NativeFarCall* at(address addr);
static bool is_at(address addr);
Expand All @@ -367,29 +358,40 @@ 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);
address dest = (address)get_data64_at(destination);

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);
}
fprintf(stderr,"CALL (%s) AT: %p loads: %p contains: %p\n", __func__, addr, destination, dest); fflush(stderr);

address NativeFarCall::reloc_destination(address orig_address) {
address call_addr = addr_at(0);
return dest;
}

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);
address NativeFarCall::reloc_destination(address orig_address, int cp_offset) {
address new_addr = addr_at(0);
assert(NativeFarCall::is_at(new_addr), "unexpected code at call site");

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");

CodeBlob* old_cb = CodeCache::find_blob(orig_address);
assert(old_cb != nullptr, "Could not find code blob");

address old_ctable = old_cb->content_begin();
address old_cp_dest = MacroAssembler::target_addr_for_insn(orig_address);
address old_dest = (address)get_data64_at(old_cp_dest);

fprintf(stderr,"CALL ORIG (%s) AT: %p loads: %p (%p) contains: %p\n", __func__, orig_address, old_cp_dest, old_ctable, old_dest); fflush(stderr);
return old_dest;
} else {
CodeBlob* new_cb = CodeCache::find_blob(new_addr);
assert(new_cb != nullptr, "Could not find code blob");

address new_ctable = new_cb->content_begin();
address new_cp_dest = MacroAssembler::target_addr_for_insn(new_addr);
address new_dest = (address)get_data64_at(new_cp_dest);
fprintf(stderr,"CALL NEW (%s) AT: %p loads: %p (%p) contains: %p\n", __func__, new_addr, new_cp_dest, new_ctable, new_dest); fflush(stderr);
return new_dest;
}
return stub_addr;
}

void NativeFarCall::set_destination(address dest) {
Expand All @@ -415,65 +417,54 @@ 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);
address cp_pool_addr = MacroAssembler::target_addr_for_insn(call_addr);

if (cp_pool_addr != nullptr) {
address dest_old = (address)get_data64_at(cp_pool_addr);
fprintf(stderr,"CALL (%s) OLD AT: %p loads: %p contains: %p\n", __func__, call_addr, cp_pool_addr, dest_old); fflush(stderr);
set_data64_at(cp_pool_addr, (uint64_t)dest);
fprintf(stderr,"CALL (%s) NEW AT: %p loads: %p contains: %p\n", __func__, call_addr, cp_pool_addr, dest); fflush(stderr);
OrderAccess::release();
return true;
} else {
fprintf(stderr,"CALL cp poll nullptr (%s) AT: %p loads: %p contains: %p\n", __func__, call_addr, cp_pool_addr, dest); fflush(stderr);
}

return false;
}

bool NativeFarCall::reloc_set_destination(address dest) {
bool NativeFarCall::reloc_set_destination(address dest, int cp_offset) {
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);

if (stub_addr != nullptr) {
MacroAssembler::pd_patch_instruction_size(call_addr, stub_addr);

CodeBlob* cb = CodeCache::find_blob(call_addr);
assert(cb != nullptr, "Could not find code blob");
nmethod* nm = cb->as_nmethod_or_null();
address ctable = cb->ctable_begin();

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) {
fprintf(stderr,"CALL (%s) (%p) patching to: %p\n", __func__, ctable, cp_entry_addr); fflush(stderr);
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());
fprintf(stderr,"CALL (%s) SET AT: %p loads: %p (%p) contains: %p\n", __func__, call_addr, cp_entry_addr, ctable, dest); fflush(stderr);
return true;
}

NativeFarCall* NativeFarCall::at(address addr) {
Expand Down Expand Up @@ -547,9 +538,9 @@ address NativeCall::destination() const {
}
}

address NativeCall::reloc_destination(address orig_address) {
address NativeCall::reloc_destination(address orig_address, int cp_offset) {
if (!UseTrampolines) {
return NativeFarCall::at(addr_at(0))->reloc_destination(orig_address);
return NativeFarCall::at(addr_at(0))->reloc_destination(orig_address, cp_offset);
} else {
return NativeShortCall::at(addr_at(0))->reloc_destination(orig_address);
}
Expand Down Expand Up @@ -587,9 +578,9 @@ bool NativeCall::set_destination_mt_safe(address dest, bool assert_lock) {
}
}

bool NativeCall::reloc_set_destination(address dest) {
bool NativeCall::reloc_set_destination(address dest, int cp_offset) {
if (!UseTrampolines) {
return NativeFarCall::at(addr_at(0))->reloc_set_destination(dest);
return NativeFarCall::at(addr_at(0))->reloc_set_destination(dest, cp_offset);
} else {
return NativeShortCall::at(addr_at(0))->reloc_set_destination(dest);
}
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/cpu/riscv/nativeInst_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,15 @@ class NativeCall: private NativeInstruction {
address next_instruction_address() const;
address return_address() const;
address destination() const;
address reloc_destination(address orig_address);
address reloc_destination(address orig_address, int cp_offset);

void verify_alignment() {} // do nothing on riscv
void verify();
void print();

void set_destination(address dest);
bool set_destination_mt_safe(address dest, bool assert_lock = true);
bool reloc_set_destination(address dest);
bool reloc_set_destination(address dest, int cp_offset);

static bool is_at(address addr);
static bool is_call_before(address return_address);
Expand Down
Loading

0 comments on commit c29aa53

Please sign in to comment.