From 8e2bd92bacd6503346a48df236959c8a959c9c77 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 3 Feb 2026 08:41:37 +0000 Subject: [PATCH] 8376970: Shenandoah: Verifier should do basic verification before touching oops Reviewed-by: wkemper, xpeng, kdnilsen --- .../gc/shenandoah/shenandoahVerifier.cpp | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 0cc6d4c6ed4..b60f8128d1d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -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 + 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__);