8261837: SIGSEGV in ciVirtualCallTypeData::translate_from
Co-authored-by: Fei Yang <fyang@openjdk.org> Reviewed-by: iveresov, vlivanov, kvn
This commit is contained in:
parent
5f7f2c4ea0
commit
1bb250c9e6
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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*) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)); }
|
||||
|
Loading…
Reference in New Issue
Block a user