8386669: AArch64: Distinguish ldr and ldrw literal instructions in NativeInstruction

Reviewed-by: aph, adinn
This commit is contained in:
Joel Sikström 2026-06-17 08:20:01 +00:00
parent ef5b328ce5
commit be837e6e61
5 changed files with 61 additions and 17 deletions

View File

@ -124,14 +124,13 @@ public:
}
};
// The first instruction of the nmethod entry barrier is an ldr (literal)
// The first instruction of the nmethod entry barrier is an ldrw (literal)
// instruction. Verify that it's really there, so the offsets are not skewed.
bool NativeNMethodBarrier::check_barrier(err_msg& msg) const {
uint32_t* addr = (uint32_t*) instruction_address();
uint32_t inst = *addr;
if ((inst & 0xff000000) != 0x18000000) {
msg.print("Nmethod entry barrier did not start with ldr (literal) as expected. "
"Addr: " PTR_FORMAT " Code: " UINT32_FORMAT, p2i(addr), inst);
NativeInstruction* ni = nativeInstruction_at(instruction_address());
if (!ni->is_ldrw_gpr_literal()) {
msg.print("Nmethod entry barrier did not start with ldrw (literal) as expected. "
"Addr: " PTR_FORMAT " Code: " UINT32_FORMAT, p2i(instruction_address()), ni->encoding());
return false;
}
return true;

View File

@ -123,7 +123,7 @@ void NativeCall::insert(address code_pos, address entry) { Unimplemented(); }
void NativeMovConstReg::verify() {
if (! (nativeInstruction_at(instruction_address())->is_movz() ||
is_adrp_at(instruction_address()) ||
is_ldr_literal_at(instruction_address())) ) {
is_load_literal_at(instruction_address())) ) {
fatal("should be MOVZ or ADRP or LDR (literal)");
}
}
@ -270,17 +270,17 @@ bool NativeInstruction::is_safepoint_poll() {
// a safepoint_poll is implemented in two steps as either
//
// adrp(reg, polling_page);
// ldr(zr, [reg, #offset]);
// ldrw(zr, [reg, #offset]);
//
// or
//
// mov(reg, polling_page);
// ldr(zr, [reg, #offset]);
// ldrw(zr, [reg, #offset]);
//
// or
//
// ldr(reg, [rthread, #offset]);
// ldr(zr, [reg, #offset]);
// ldrw(zr, [reg, #offset]);
//
// however, we cannot rely on the polling page address load always
// directly preceding the read from the page. C1 does that but C2
@ -301,11 +301,21 @@ bool NativeInstruction::is_adrp_at(address instr) {
return (Instruction_aarch64::extract(insn, 31, 24) & 0b10011111) == 0b10010000;
}
bool NativeInstruction::is_ldr_literal_at(address instr) {
bool NativeInstruction::is_load_literal_at(address instr) {
unsigned insn = *(unsigned*)instr;
return (Instruction_aarch64::extract(insn, 29, 24) & 0b011011) == 0b00011000;
}
bool NativeInstruction::is_ldr_gpr_literal_at(address instr) {
unsigned insn = *(unsigned*)instr;
return Instruction_aarch64::extract(insn, 31, 24) == 0b01011000;
}
bool NativeInstruction::is_ldrw_gpr_literal_at(address instr) {
unsigned insn = *(unsigned*)instr;
return Instruction_aarch64::extract(insn, 31, 24) == 0b00011000;
}
bool NativeInstruction::is_ldrw_to_zr(address instr) {
unsigned insn = *(unsigned*)instr;
return (Instruction_aarch64::extract(insn, 31, 22) == 0b1011100101 &&

View File

@ -107,10 +107,22 @@ public:
static bool is_adrp_at(address instr);
static bool is_ldr_literal_at(address instr);
static bool is_load_literal_at(address instr);
bool is_ldr_literal() {
return is_ldr_literal_at(addr_at(0));
bool is_load_literal() {
return is_load_literal_at(addr_at(0));
}
static bool is_ldr_gpr_literal_at(address instr);
bool is_ldr_gpr_literal() {
return is_ldr_gpr_literal_at(addr_at(0));
}
static bool is_ldrw_gpr_literal_at(address instr);
bool is_ldrw_gpr_literal() {
return is_ldrw_gpr_literal_at(addr_at(0));
}
static bool is_ldrw_to_zr(address instr);
@ -125,7 +137,7 @@ public:
}
static bool maybe_cpool_ref(address instr) {
return is_adrp_at(instr) || is_ldr_literal_at(instr);
return is_adrp_at(instr) || is_load_literal_at(instr);
}
bool is_Membar() {
@ -267,7 +279,7 @@ public:
return addr_at(instruction_size);
else if (is_adrp_at(instruction_address()))
return addr_at(2*4);
else if (is_ldr_literal_at(instruction_address()))
else if (is_load_literal_at(instruction_address()))
return(addr_at(4));
assert(false, "Unknown instruction in NativeMovConstReg");
return nullptr;

View File

@ -41,7 +41,7 @@ void Relocation::pd_set_data_value(address x, bool verify_only) {
case relocInfo::oop_type:
{
oop_Relocation *reloc = (oop_Relocation *)this;
if (NativeInstruction::is_ldr_literal_at(addr())) {
if (NativeInstruction::is_load_literal_at(addr())) {
address constptr = (address)code()->oop_addr_at(reloc->oop_index());
bytes = MacroAssembler::pd_patch_instruction_size(addr(), constptr);
assert(*(address*)constptr == x, "error in oop relocation");

View File

@ -488,4 +488,27 @@ TEST_VM(AssemblerAArch64, merge_ldst_after_expand) {
asm_check((const unsigned int *)code.insts()->start(), insns, sizeof insns / sizeof insns[0]);
}
TEST_VM(AssemblerAArch64, native_instruction_load_predicates) {
static uint32_t insns[] = {
0x58000000, // ldr x0, #0
0x18000000, // ldr w0, #0
0x1C000000, // ldr s0, #0 (VR bit set to 1, enabling SIMD/FP register)
};
NativeInstruction* ni_ldr = nativeInstruction_at(&insns[0]);
EXPECT_TRUE(ni_ldr->is_load_literal());
EXPECT_TRUE(ni_ldr->is_ldr_gpr_literal());
EXPECT_FALSE(ni_ldr->is_ldrw_gpr_literal());
NativeInstruction* ni_ldrw = nativeInstruction_at(&insns[1]);
EXPECT_TRUE(ni_ldrw->is_load_literal());
EXPECT_FALSE(ni_ldrw->is_ldr_gpr_literal());
EXPECT_TRUE(ni_ldrw->is_ldrw_gpr_literal());
NativeInstruction* ni_ldrs = nativeInstruction_at(&insns[2]);
EXPECT_TRUE(ni_ldrs->is_load_literal());
EXPECT_FALSE(ni_ldrs->is_ldr_gpr_literal());
EXPECT_FALSE(ni_ldrs->is_ldrw_gpr_literal());
}
#endif // AARCH64