Skip to content

Commit

Permalink
far and short
Browse files Browse the repository at this point in the history
  • Loading branch information
robehn committed Mar 21, 2024
1 parent cc5eed9 commit 8508e36
Show file tree
Hide file tree
Showing 3 changed files with 268 additions and 102 deletions.
4 changes: 2 additions & 2 deletions src/hotspot/cpu/riscv/jvmciCodeInstaller_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,9 @@ void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong forei
address pc = (address) inst;
if (inst->is_jal()) {
assert(false, "Bad");
/* NativeCall* call = nativeCall_at(pc);
NativeCall* call = nativeCall_at(pc);
call->set_destination((address) foreign_call_destination);
_instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());*/
_instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
} else if (inst->is_jump()) {
NativeJump* jump = nativeJump_at(pc);
jump->set_jump_destination((address) foreign_call_destination);
Expand Down
228 changes: 189 additions & 39 deletions src/hotspot/cpu/riscv/nativeInst_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include "c1/c1_Runtime1.hpp"
#endif

//-----------------------------------------------------------------------------
// NativeInstruction
Register NativeInstruction::extract_rs1(address instr) {
assert_cond(instr != nullptr);
return as_Register(Assembler::extract(Assembler::ld_instr(instr), 19, 15));
Expand Down Expand Up @@ -120,11 +122,81 @@ bool NativeInstruction::is_li64_at(address instr) {
check_li64_data_dependency(instr);
}

void NativeCall::verify() {
assert(is_load_pc_relative_at(instruction_address()), "unexpected code at call site: %p", (address)this);
//-----------------------------------------------------------------------------
// NativeShortCall

address NativeShortCall::destination() const {
address addr = (address)this;
assert(NativeShortCall::is_at(addr), "unexpected code at call site");
assert(NativeInstruction::is_jal_at(instruction_address()), "inst must be jal.");
address destination = MacroAssembler::target_addr_for_insn(instruction_address());
return destination;
}

address NativeCall::destination() const {
void NativeShortCall::set_destination(address dest) {
assert(NativeShortCall::is_at((address)this), "unexpected code at call site");
}

void NativeShortCall::verify() {
assert(NativeShortCall::is_at((address)this), "unexpected code at call site");
}

void NativeShortCall::print() {
assert(NativeShortCall::is_at((address)this), "unexpected code at call site");
tty->print_cr(PTR_FORMAT ": jal/auipc,ld,jalr x1, offset/reg", p2i(instruction_address()));
}

void NativeShortCall::set_destination_mt_safe(address dest, bool assert_lock) {
assert(NativeShortCall::is_at((address)this), "unexpected code at call site");
assert(!assert_lock ||
(Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) ||
CompiledICLocker::is_safe(addr_at(0)),
"concurrent code patching");

address addr_call = addr_at(0);
// Patch the call.
assert(Assembler::reachable_from_branch_at(addr_call, dest), "we need a trampoline");
set_destination(dest);

ICache::invalidate_range(addr_call, instruction_size);
}

NativeShortCall* NativeShortCall::at(address addr) {
assert_cond(addr != nullptr);
assert(NativeShortCall::is_at(addr), "unexpected code at call site");
NativeShortCall* call = (NativeShortCall*)(addr);
return call;
}

bool NativeShortCall::is_at(address addr) {
assert(!is_jalr_at(addr), "What?");
if (is_jal_at(addr)) {
if (NativeInstruction::extract_rd(addr) == x1) {
return true;
}
}
return false;
}

bool NativeShortCall::is_call_before(address return_address) {
assert(NativeShortCall::is_at(return_address - Assembler::instruction_size), "unexpected code at call site");
return false;
}

void NativeShortCall::insert(address code_pos, address entry) {
Unimplemented();
}

void NativeShortCall::replace_mt_safe(address instr_addr, address code_buffer) {
Unimplemented();
}

//-----------------------------------------------------------------------------
// NativeFarCall

address NativeFarCall::destination() const {
assert(NativeFarCall::is_at((address)this), "unexpected code at call site");

address addr = (address)this;
assert(is_load_pc_relative_at(instruction_address()), "Must be");
address destination = MacroAssembler::target_addr_for_insn(instruction_address());
Expand All @@ -133,75 +205,153 @@ address NativeCall::destination() const {
CodeBlob* cb = CodeCache::find_blob(addr);
assert(cb && cb->is_nmethod(), "sanity");
nmethod *nm = (nmethod *)cb;
if (nm != nullptr && nm->stub_contains(destination) && is_NativeCallTrampolineStub_at(destination)) {
// Yes we do, so get the destination from the trampoline stub.
const address trampoline_stub_addr = destination;
destination = nativeCallTrampolineStub_at(trampoline_stub_addr)->destination();
}
assert(nm != nullptr && nm->stub_contains(destination), "No tramp");
assert(is_NativeCallTrampolineStub_at(destination), "Must be");

destination = nativeCallTrampolineStub_at(destination)->destination();

return destination;
}

void NativeCall::set_destination(address dest) {
void NativeFarCall::set_destination(address dest) {
assert(NativeFarCall::is_at((address)this), "unexpected code at call site");
assert(is_load_pc_relative_at(instruction_address()), "Must be");
MacroAssembler::pd_patch_instruction_size(instruction_address(), (address)dest);
}

// Similar to replace_mt_safe, but just changes the destination. The
// important thing is that free-running threads are able to execute this
// call instruction at all times.
//
// Used in the runtime linkage of calls; see class CompiledIC.
//
// Add parameter assert_lock to switch off assertion
// during code generation, where no patching lock is needed.
void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) {
assert(false, "Fix me");
// MacroAssembler::pd_patch_instruction_size(instruction_address(), (address)dest);
}

void NativeFarCall::verify() {
assert(NativeFarCall::is_at((address)this), "unexpected code at call site");
}

void NativeFarCall::print() {
assert(NativeFarCall::is_at((address)this), "unexpected code at call site");
tty->print_cr(PTR_FORMAT ": jal/auipc,ld,jalr x1, offset/reg, ", p2i(instruction_address()));
}

void NativeFarCall::set_destination_mt_safe(address dest, bool assert_lock) {
assert(NativeFarCall::is_at((address)this), "unexpected code at call site");
assert(!assert_lock ||
(Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) ||
CompiledICLocker::is_safe(addr_at(0)),
"concurrent code patching");

address addr_call = addr_at(0);
assert(NativeCall::is_call_at(addr_call), "unexpected code at call site");
assert(NativeFarCall::is_at(addr_call), "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) {
assert (!is_NativeCallTrampolineStub_at(dest), "chained trampolines");
nativeCallTrampolineStub_at(trampoline_stub_addr)->set_destination(dest);
}

// Patch the call.
if (Assembler::reachable_from_branch_at(addr_call, dest)) {
set_destination(dest);
} else {
assert (trampoline_stub_addr != nullptr, "we need a trampoline");
set_destination(trampoline_stub_addr);
}
assert(trampoline_stub_addr != nullptr, "Must be");
assert (!is_NativeCallTrampolineStub_at(dest), "chained trampolines");
nativeCallTrampolineStub_at(trampoline_stub_addr)->set_destination(dest);

ICache::invalidate_range(addr_call, instruction_size);
}

address NativeCall::get_trampoline() {
address NativeFarCall::get_trampoline() {
address call_addr = addr_at(0);

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

assert(false, "Fix me");

/*
address jal_destination = MacroAssembler::pd_call_destination(call_addr);
if (code != nullptr && code->contains(jal_destination) && is_NativeCallTrampolineStub_at(jal_destination)) {
if (code != nullptr && code->contains(jal_destination) && is_NativeFarCallTrampolineStub_at(jal_destination)) {
return jal_destination;
}
if (code != nullptr && code->is_nmethod()) {
return trampoline_stub_Relocation::get_trampoline_for(call_addr, (nmethod*)code);
}

*/
return nullptr;
}

// Inserts a native call instruction at a given pc
void NativeCall::insert(address code_pos, address entry) { Unimplemented(); }
NativeFarCall* NativeFarCall::at(address addr) {
assert_cond(addr != nullptr);
assert(NativeFarCall::is_at(addr), "unexpected code at call site");
NativeFarCall* call = (NativeFarCall*)(addr);
return call;
}

bool NativeFarCall::is_at(address addr) {
assert_cond(addr != nullptr);
const int instr_size = NativeInstruction::instruction_size;
if (NativeInstruction::is_auipc_at(addr) &&
NativeInstruction::is_ld_at(addr + instr_size) &&
NativeInstruction::is_jalr_at(addr + 2 * instr_size) &&
(NativeInstruction::extract_rd(addr) == x5) &&
(NativeInstruction::extract_rd(addr + instr_size) == x5) &&
(NativeInstruction::extract_rs1(addr + instr_size) == x5) &&
(NativeInstruction::extract_rs1(addr + 2 * instr_size) == x5) &&
(NativeInstruction::extract_rd(addr + 2 * instr_size) == x1)) {
return true;
}
return false;
}

bool NativeFarCall::is_call_before(address return_address) {
return false;
}

void NativeFarCall::insert(address code_pos, address entry) {
Unimplemented();
}

void NativeFarCall::replace_mt_safe(address instr_addr, address code_buffer) {
}


//-----------------------------------------------------------------------------
// NativeCall

address NativeCall::instruction_address() const {
if (NativeShortCall::is_at(address(this))) {
return NativeShortCall::at(address(this))->instruction_address();
}
return 0;
}

address NativeCall::next_instruction_address() const {
return 0;
}

address NativeCall::return_address() const {
return 0;
}

address NativeCall::destination() const {
return 0;
}

void NativeCall::set_destination(address dest) {
}

void NativeCall::verify() {
}

void NativeCall::print() {
tty->print_cr(PTR_FORMAT ": jal/auipc,ld,jalr x1, offset/reg", p2i(instruction_address()));
}

void NativeCall::set_destination_mt_safe(address dest, bool assert_lock = true) {
}

address NativeCall::get_trampoline() {
return 0;
}

bool NativeCall::is_call_before(address return_address) {
return false;
}

void NativeCall::insert(address code_pos, address entry) {
}

void NativeCall::replace_mt_safe(address instr_addr, address code_buffer) {
}

//-------------------------------------------------------------------

Expand Down
Loading

0 comments on commit 8508e36

Please sign in to comment.