8261837: SIGSEGV in ciVirtualCallTypeData::translate_from

Co-authored-by: Fei Yang <fyang@openjdk.org>
Reviewed-by: iveresov, vlivanov, kvn
This commit is contained in:
Dean Long 2023-11-27 22:01:37 +00:00
parent 5f7f2c4ea0
commit 1bb250c9e6
7 changed files with 115 additions and 39 deletions

View File

@ -2699,7 +2699,10 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
__ verify_oop(obj);
if (tmp != obj) {
assert_different_registers(obj, tmp, rscratch1, rscratch2, mdo_addr.base(), mdo_addr.index());
__ mov(tmp, obj);
} else {
assert_different_registers(obj, rscratch1, rscratch2, mdo_addr.base(), mdo_addr.index());
}
if (do_null) {
__ cbnz(tmp, update);
@ -2756,10 +2759,11 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
__ cbz(rscratch2, none);
__ cmp(rscratch2, (u1)TypeEntries::null_seen);
__ br(Assembler::EQ, none);
// There is a chance that the checks above (re-reading profiling
// data from memory) fail if another thread has just set the
// There is a chance that the checks above
// fail if another thread has just set the
// profiling to this obj's klass
__ dmb(Assembler::ISHLD);
__ eor(tmp, tmp, rscratch2); // get back original value before XOR
__ ldr(rscratch2, mdo_addr);
__ eor(tmp, tmp, rscratch2);
__ andr(rscratch1, tmp, TypeEntries::type_klass_mask);
@ -2784,6 +2788,10 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
__ bind(none);
// first time here. Set profile type.
__ str(tmp, mdo_addr);
#ifdef ASSERT
__ andr(tmp, tmp, TypeEntries::type_mask);
__ verify_klass_ptr(tmp);
#endif
}
} else {
// There's a single possible klass at this profile point
@ -2815,6 +2823,10 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
#endif
// first time here. Set profile type.
__ str(tmp, mdo_addr);
#ifdef ASSERT
__ andr(tmp, tmp, TypeEntries::type_mask);
__ verify_klass_ptr(tmp);
#endif
} else {
assert(ciTypeEntries::valid_ciklass(current_klass) != nullptr &&
ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent");

View File

@ -1562,7 +1562,7 @@ void InterpreterMacroAssembler::call_VM_base(Register oop_result,
}
void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
assert_different_registers(obj, rscratch1);
assert_different_registers(obj, rscratch1, mdo_addr.base(), mdo_addr.index());
Label update, next, none;
verify_oop(obj);
@ -1584,13 +1584,13 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& md
tbnz(obj, exact_log2(TypeEntries::type_unknown), next);
// already unknown. Nothing to do anymore.
ldr(rscratch1, mdo_addr);
cbz(rscratch1, none);
cmp(rscratch1, (u1)TypeEntries::null_seen);
br(Assembler::EQ, none);
// There is a chance that the checks above (re-reading profiling
// data from memory) fail if another thread has just set the
// There is a chance that the checks above
// fail if another thread has just set the
// profiling to this obj's klass
eor(obj, obj, rscratch1); // get back original value before XOR
ldr(rscratch1, mdo_addr);
eor(obj, obj, rscratch1);
tst(obj, TypeEntries::type_klass_mask);
@ -1603,6 +1603,10 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& md
bind(none);
// first time here. Set profile type.
str(obj, mdo_addr);
#ifdef ASSERT
andr(obj, obj, TypeEntries::type_mask);
verify_klass_ptr(obj);
#endif
bind(next);
}

View File

@ -1653,10 +1653,11 @@ void LIR_Assembler::check_conflict(ciKlass* exact_klass, intptr_t current_klass,
__ beqz(t1, none);
__ mv(t0, (u1)TypeEntries::null_seen);
__ beq(t0, t1, none);
// There is a chance that the checks above (re-reading profiling
// data from memory) fail if another thread has just set the
// There is a chance that the checks above
// fail if another thread has just set the
// profiling to this obj's klass
__ membar(MacroAssembler::LoadLoad);
__ xorr(tmp, tmp, t1); // get back original value before XOR
__ ld(t1, mdo_addr);
__ xorr(tmp, tmp, t1);
__ andi(t0, tmp, TypeEntries::type_klass_mask);
@ -1683,6 +1684,10 @@ void LIR_Assembler::check_conflict(ciKlass* exact_klass, intptr_t current_klass,
__ bind(none);
// first time here. Set profile type.
__ sd(tmp, mdo_addr);
#ifdef ASSERT
__ andi(tmp, tmp, TypeEntries::type_mask);
__ verify_klass_ptr(tmp);
#endif
}
}
@ -1717,6 +1722,10 @@ void LIR_Assembler::check_no_conflict(ciKlass* exact_klass, intptr_t current_kla
#endif
// first time here. Set profile type.
__ sd(tmp, mdo_addr);
#ifdef ASSERT
__ andi(tmp, tmp, TypeEntries::type_mask);
__ verify_klass_ptr(tmp);
#endif
} else {
assert(ciTypeEntries::valid_ciklass(current_klass) != nullptr &&
ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent");

View File

@ -1627,8 +1627,8 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& md
bind(update);
load_klass(obj, obj);
ld(t0, mdo_addr);
xorr(obj, obj, t0);
ld(tmp, mdo_addr);
xorr(obj, obj, tmp);
andi(t0, obj, TypeEntries::type_klass_mask);
beqz(t0, next); // klass seen before, nothing to
// do. The unknown bit may have been
@ -1638,15 +1638,15 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& md
bnez(t0, next);
// already unknown. Nothing to do anymore.
ld(t0, mdo_addr);
beqz(t0, none);
mv(tmp, (u1)TypeEntries::null_seen);
beq(t0, tmp, none);
// There is a chance that the checks above (re-reading profiling
// data from memory) fail if another thread has just set the
beqz(tmp, none);
mv(t0, (u1)TypeEntries::null_seen);
beq(tmp, t0, none);
// There is a chance that the checks above
// fail if another thread has just set the
// profiling to this obj's klass
ld(t0, mdo_addr);
xorr(obj, obj, t0);
xorr(obj, obj, tmp); // get back original value before XOR
ld(tmp, mdo_addr);
xorr(obj, obj, tmp);
andi(t0, obj, TypeEntries::type_klass_mask);
beqz(t0, next);
@ -1657,6 +1657,10 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& md
bind(none);
// first time here. Set profile type.
sd(obj, mdo_addr);
#ifdef ASSERT
andi(obj, obj, TypeEntries::type_mask);
verify_klass_ptr(obj);
#endif
bind(next);
}

View File

@ -3629,13 +3629,33 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
__ verify_oop(obj);
if (tmp != obj) {
__ mov(tmp, obj);
#ifdef ASSERT
if (obj == tmp) {
#ifdef _LP64
assert_different_registers(obj, rscratch1, mdo_addr.base(), mdo_addr.index());
#else
assert_different_registers(obj, mdo_addr.base(), mdo_addr.index());
#endif
} else {
#ifdef _LP64
assert_different_registers(obj, tmp, rscratch1, mdo_addr.base(), mdo_addr.index());
#else
assert_different_registers(obj, tmp, mdo_addr.base(), mdo_addr.index());
#endif
}
#endif
if (do_null) {
__ testptr(tmp, tmp);
__ testptr(obj, obj);
__ jccb(Assembler::notZero, update);
if (!TypeEntries::was_null_seen(current_klass)) {
__ testptr(mdo_addr, TypeEntries::null_seen);
#ifndef ASSERT
__ jccb(Assembler::notZero, next); // already set
#else
__ jcc(Assembler::notZero, next); // already set
#endif
// atomic update to prevent overwriting Klass* with 0
__ lock();
__ orptr(mdo_addr, TypeEntries::null_seen);
}
if (do_update) {
@ -3646,7 +3666,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
__ jmp(next);
}
} else {
__ testptr(tmp, tmp);
__ testptr(obj, obj);
__ jcc(Assembler::notZero, update);
__ stop("unexpected null obj");
#endif
@ -3658,7 +3678,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
#ifdef ASSERT
if (exact_klass != nullptr) {
Label ok;
__ load_klass(tmp, tmp, tmp_load_klass);
__ load_klass(tmp, obj, tmp_load_klass);
__ push(tmp);
__ mov_metadata(tmp, exact_klass->constant_encoding());
__ cmpptr(tmp, Address(rsp, 0));
@ -3673,9 +3693,11 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
if (exact_klass != nullptr) {
__ mov_metadata(tmp, exact_klass->constant_encoding());
} else {
__ load_klass(tmp, tmp, tmp_load_klass);
__ load_klass(tmp, obj, tmp_load_klass);
}
#ifdef _LP64
__ mov(rscratch1, tmp); // save original value before XOR
#endif
__ xorptr(tmp, mdo_addr);
__ testptr(tmp, TypeEntries::type_klass_mask);
// klass seen before, nothing to do. The unknown bit may have been
@ -3686,23 +3708,23 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
__ jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
if (TypeEntries::is_type_none(current_klass)) {
__ cmpptr(mdo_addr, 0);
__ jccb(Assembler::equal, none);
__ cmpptr(mdo_addr, TypeEntries::null_seen);
__ jccb(Assembler::equal, none);
__ testptr(mdo_addr, TypeEntries::type_mask);
__ jccb(Assembler::zero, none);
#ifdef _LP64
// There is a chance that the checks above (re-reading profiling
// data from memory) fail if another thread has just set the
// profiling to this obj's klass
__ mov(tmp, rscratch1); // get back original value before XOR
__ xorptr(tmp, mdo_addr);
__ testptr(tmp, TypeEntries::type_klass_mask);
__ jccb(Assembler::zero, next);
#endif
}
} else {
assert(ciTypeEntries::valid_ciklass(current_klass) != nullptr &&
ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "conflict only");
__ movptr(tmp, mdo_addr);
__ testptr(tmp, TypeEntries::type_unknown);
__ testptr(mdo_addr, TypeEntries::type_unknown);
__ jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
}
@ -3715,6 +3737,10 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
__ bind(none);
// first time here. Set profile type.
__ movptr(mdo_addr, tmp);
#ifdef ASSERT
__ andptr(tmp, TypeEntries::type_klass_mask);
__ verify_klass_ptr(tmp);
#endif
}
} else {
// There's a single possible klass at this profile point
@ -3729,10 +3755,8 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
{
Label ok;
__ push(tmp);
__ cmpptr(mdo_addr, 0);
__ jcc(Assembler::equal, ok);
__ cmpptr(mdo_addr, TypeEntries::null_seen);
__ jcc(Assembler::equal, ok);
__ testptr(mdo_addr, TypeEntries::type_mask);
__ jcc(Assembler::zero, ok);
// may have been set by another thread
__ mov_metadata(tmp, exact_klass->constant_encoding());
__ xorptr(tmp, mdo_addr);
@ -3748,20 +3772,22 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
#endif
// first time here. Set profile type.
__ movptr(mdo_addr, tmp);
#ifdef ASSERT
__ andptr(tmp, TypeEntries::type_klass_mask);
__ verify_klass_ptr(tmp);
#endif
} else {
assert(ciTypeEntries::valid_ciklass(current_klass) != nullptr &&
ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent");
__ movptr(tmp, mdo_addr);
__ testptr(tmp, TypeEntries::type_unknown);
__ testptr(mdo_addr, TypeEntries::type_unknown);
__ jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
__ orptr(mdo_addr, TypeEntries::type_unknown);
}
}
__ bind(next);
}
__ bind(next);
}
void LIR_Assembler::emit_delay(LIR_OpDelay*) {

View File

@ -54,15 +54,28 @@ void InterpreterMacroAssembler::jump_to_entry(address entry) {
void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
Label update, next, none;
#ifdef _LP64
assert_different_registers(obj, rscratch1, mdo_addr.base(), mdo_addr.index());
#else
assert_different_registers(obj, mdo_addr.base(), mdo_addr.index());
#endif
interp_verify_oop(obj, atos);
testptr(obj, obj);
jccb(Assembler::notZero, update);
testptr(mdo_addr, TypeEntries::null_seen);
jccb(Assembler::notZero, next); // null already seen. Nothing to do anymore.
// atomic update to prevent overwriting Klass* with 0
lock();
orptr(mdo_addr, TypeEntries::null_seen);
jmpb(next);
bind(update);
load_klass(obj, obj, rscratch1);
#ifdef _LP64
mov(rscratch1, obj);
#endif
xorptr(obj, mdo_addr);
testptr(obj, TypeEntries::type_klass_mask);
@ -77,12 +90,15 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& md
jccb(Assembler::equal, none);
cmpptr(mdo_addr, TypeEntries::null_seen);
jccb(Assembler::equal, none);
#ifdef _LP64
// There is a chance that the checks above (re-reading profiling
// data from memory) fail if another thread has just set the
// profiling to this obj's klass
mov(obj, rscratch1);
xorptr(obj, mdo_addr);
testptr(obj, TypeEntries::type_klass_mask);
jccb(Assembler::zero, next);
#endif
// different than before. Cannot keep accurate profile.
orptr(mdo_addr, TypeEntries::type_unknown);
@ -91,6 +107,10 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& md
bind(none);
// first time here. Set profile type.
movptr(mdo_addr, obj);
#ifdef ASSERT
andptr(obj, TypeEntries::type_klass_mask);
verify_klass_ptr(obj);
#endif
bind(next);
}

View File

@ -894,6 +894,7 @@ public:
void testptr(Register src, int32_t imm32) { LP64_ONLY(testq(src, imm32)) NOT_LP64(testl(src, imm32)); }
void testptr(Register src1, Address src2) { LP64_ONLY(testq(src1, src2)) NOT_LP64(testl(src1, src2)); }
void testptr(Address src, int32_t imm32) { LP64_ONLY(testq(src, imm32)) NOT_LP64(testl(src, imm32)); }
void testptr(Register src1, Register src2);
void xorptr(Register dst, Register src) { LP64_ONLY(xorq(dst, src)) NOT_LP64(xorl(dst, src)); }