8376970: Shenandoah: Verifier should do basic verification before touching oops

Reviewed-by: wkemper, xpeng, kdnilsen
This commit is contained in:
Aleksey Shipilev 2026-02-03 08:41:37 +00:00
parent e21cb8525d
commit 8e2bd92bac

View File

@ -110,15 +110,15 @@ private:
void do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
oop obj = CompressedOops::decode_not_null(o);
// Basic verification should happen before we touch anything else.
// For performance reasons, only fully verify non-marked field values.
// We are here when the host object for *p is already marked.
oop obj = CompressedOops::decode_raw_not_null(o);
verify_oop_at_basic(p, obj);
if (is_instance_ref_klass(ShenandoahForwarding::klass(obj))) {
obj = ShenandoahForwarding::get_forwardee(obj);
}
// Single threaded verification can use faster non-atomic stack and bitmap
// methods.
//
// For performance reasons, only fully verify non-marked field values.
// We are here when the host object for *p is already marked.
if (in_generation(obj) && _map->par_mark(obj)) {
verify_oop_at(p, obj);
_stack->push(ShenandoahVerifierTask(obj));
@ -131,7 +131,7 @@ private:
return _generation->contains(region);
}
void verify_oop(oop obj) {
void verify_oop(oop obj, bool basic = false) {
// Perform consistency checks with gradually decreasing safety level. This guarantees
// that failure report would not try to touch something that was not yet verified to be
// safe to process.
@ -174,10 +174,14 @@ private:
}
}
check(ShenandoahAsserts::_safe_unknown, obj, obj_reg->is_active(),
"Object should be in active region");
// ------------ obj is safe at this point --------------
check(ShenandoahAsserts::_safe_oop, obj, obj_reg->is_active(),
"Object should be in active region");
if (basic) {
return;
}
switch (_options._verify_liveness) {
case ShenandoahVerifier::_verify_liveness_disable:
@ -331,6 +335,18 @@ public:
_interior_loc = nullptr;
}
/**
* Verify object with known interior reference, with only basic verification.
* @param p interior reference where the object is referenced from; can be off-heap
* @param obj verified object
*/
template <class T>
void verify_oop_at_basic(T* p, oop obj) {
_interior_loc = p;
verify_oop(obj, /* basic = */ true);
_interior_loc = nullptr;
}
/**
* Verify object without known interior reference.
* Useful when picking up the object at known offset in heap,
@ -1232,7 +1248,9 @@ private:
void do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
oop obj = CompressedOops::decode_not_null(o);
oop obj = CompressedOops::decode_raw_not_null(o);
ShenandoahAsserts::assert_correct(p, obj, __FILE__, __LINE__);
oop fwd = ShenandoahForwarding::get_forwardee_raw_unchecked(obj);
if (obj != fwd) {
ShenandoahAsserts::print_failure(ShenandoahAsserts::_safe_all, obj, p, nullptr,
@ -1252,7 +1270,9 @@ private:
void do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
oop obj = CompressedOops::decode_not_null(o);
oop obj = CompressedOops::decode_raw_not_null(o);
ShenandoahAsserts::assert_correct(p, obj, __FILE__, __LINE__);
ShenandoahHeap* heap = ShenandoahHeap::heap();
if (!heap->marking_context()->is_marked_or_old(obj)) {
@ -1306,7 +1326,9 @@ public:
inline void work(T* p) {
T o = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(o)) {
oop obj = CompressedOops::decode_not_null(o);
oop obj = CompressedOops::decode_raw_not_null(o);
ShenandoahAsserts::assert_correct(p, obj, __FILE__, __LINE__);
if (_heap->is_in_young(obj) && !_scanner->is_card_dirty((HeapWord*) p)) {
ShenandoahAsserts::print_failure(ShenandoahAsserts::_safe_all, obj, p, nullptr,
_message, "clean card, it should be dirty.", __FILE__, __LINE__);