8298075: RISC-V: Implement post-call NOPs

Reviewed-by: fyang, luhenry
This commit is contained in:
Xiaolin Zheng 2022-12-08 02:19:35 +00:00 committed by Fei Yang
parent 3aa4070d4c
commit 74f346b33f
6 changed files with 37 additions and 7 deletions

@ -43,7 +43,9 @@ void C1SafepointPollStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
InternalAddress safepoint_pc(__ pc() - __ offset() + safepoint_offset());
__ relocate(safepoint_pc.rspec(), [&] {
__ la(t0, safepoint_pc.target());
int32_t offset;
__ la_patchable(t0, safepoint_pc.target(), offset);
__ addi(t0, t0, offset);
});
__ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset()));

@ -40,7 +40,9 @@ void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointP
__ bind(entry->_stub_label);
InternalAddress safepoint_pc(__ pc() - __ offset() + entry->_safepoint_offset);
__ relocate(safepoint_pc.rspec(), [&] {
__ la(t0, safepoint_pc.target());
int32_t offset;
__ la_patchable(t0, safepoint_pc.target(), offset);
__ addi(t0, t0, offset);
});
__ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset()));
__ far_jump(callback_addr);

@ -210,6 +210,7 @@ void MacroAssembler::post_call_nop() {
}
relocate(post_call_nop_Relocation::spec(), [&] {
nop();
li32(zr, 0);
});
}
@ -1383,7 +1384,7 @@ static int patch_imm_in_li64(address branch, address target) {
return LI64_INSTRUCTIONS_NUM * NativeInstruction::instruction_size;
}
static int patch_imm_in_li32(address branch, int32_t target) {
int MacroAssembler::patch_imm_in_li32(address branch, int32_t target) {
const int LI32_INSTRUCTIONS_NUM = 2; // lui + addiw
int64_t upper = (intptr_t)target;
int32_t lower = (((int32_t)target) << 20) >> 20;
@ -1447,7 +1448,7 @@ static address get_target_of_li64(address insn_addr) {
return (address)target_address;
}
static address get_target_of_li32(address insn_addr) {
address MacroAssembler::get_target_of_li32(address insn_addr) {
assert_cond(insn_addr != NULL);
intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 12; // Lui.
target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)); // Addiw.

@ -387,6 +387,9 @@ class MacroAssembler: public Assembler {
static int patch_oop(address insn_addr, address o);
static address get_target_of_li32(address insn_addr);
static int patch_imm_in_li32(address branch, int32_t target);
// Return whether code is emitted to a scratch blob.
virtual bool in_scratch_emit_size() {
return false;

@ -444,8 +444,16 @@ void NativePostCallNop::make_deopt() {
NativeDeoptInstruction::insert(addr_at(0));
}
int NativePostCallNop::displacement() const {
// Discard the high 32 bits
return (int)(intptr_t)MacroAssembler::get_target_of_li32(addr_at(4));
}
void NativePostCallNop::patch(jint diff) {
// unsupported for now
assert(diff != 0, "must be");
assert(is_lui_to_zr_at(addr_at(4)) && is_addiw_to_zr_at(addr_at(8)), "must be");
MacroAssembler::patch_imm_in_li32(addr_at(4), diff);
}
void NativeDeoptInstruction::verify() {

@ -78,7 +78,9 @@ class NativeInstruction {
static bool is_jump_at(address instr) { assert_cond(instr != NULL); return is_branch_at(instr) || is_jal_at(instr) || is_jalr_at(instr); }
static bool is_addi_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0010011 && extract_funct3(instr) == 0b000; }
static bool is_addiw_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0011011 && extract_funct3(instr) == 0b000; }
static bool is_addiw_to_zr_at(address instr) { assert_cond(instr != NULL); return is_addiw_at(instr) && extract_rd(instr) == zr; }
static bool is_lui_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0110111; }
static bool is_lui_to_zr_at(address instr) { assert_cond(instr != NULL); return is_lui_at(instr) && extract_rd(instr) == zr; }
static bool is_slli_shift_at(address instr, uint32_t shift) {
assert_cond(instr != NULL);
return (extract_opcode(instr) == 0b0010011 && // opcode field
@ -554,10 +556,22 @@ inline NativeMembar *NativeMembar_at(address addr) {
return (NativeMembar*)addr;
}
// A NativePostCallNop takes the form of three instructions:
// nop; lui zr, hi20; addiw zr, lo12
//
// The nop is patchable for a deoptimization trap. The lui and addiw
// instructions execute as nops but have a 20/12-bit payload in which we
// can store an offset from the initial nop to the nmethod.
class NativePostCallNop: public NativeInstruction {
public:
bool check() const { return is_nop(); }
int displacement() const { return 0; }
bool check() const {
// Check for two instructions: nop; lui zr, hi20
// These instructions only ever appear together in a post-call
// NOP, so it's unnecessary to check that the third instruction is
// an addiw as well.
return is_nop() && is_lui_to_zr_at(addr_at(4));
}
int displacement() const;
void patch(jint diff);
void make_deopt();
};