From 5fdf0c54dbe446a2828d4e97c4657de63deaa712 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Fri, 12 Jun 2026 21:30:19 +0000 Subject: [PATCH 1/2] Backport a13dd293a811a6ba829696e68cd2150de2cb2f17 --- src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp | 1 + .../share/gc/shenandoah/shenandoahMarkingContext.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp index 20040eebafd..c9a4aa5d44c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp @@ -269,6 +269,7 @@ class ShenandoahHeapRegion { ShenandoahSharedFlag _recycling; // Used to indicate that the region is being recycled; see try_recycle*(). + // This is only read/written by a gc worker to avoid unnecessary bitmap resets bool _needs_bitmap_reset; public: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp index 40eee8c342b..0bcdfa9fd2c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved. + * Copyright (c) 2018, 2026, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ #include "gc/shared/markBitMap.inline.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.hpp" -#include "shenandoahGlobalGeneration.hpp" +#include "runtime/orderAccess.hpp" ShenandoahMarkingContext::ShenandoahMarkingContext(MemRegion heap_region, MemRegion bitmap_region, size_t num_regions) : _mark_bit_map(heap_region, bitmap_region), @@ -91,6 +91,7 @@ void ShenandoahMarkingContext::clear_bitmap(ShenandoahHeapRegion* r) { if (top_bitmap > bottom) { _mark_bit_map.clear_range_large(MemRegion(bottom, top_bitmap)); + OrderAccess::storestore(); _top_bitmaps[r->index()] = bottom; } From 7fd8de8878b4b4c68ffb11d56efd24dcb5963ac6 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Fri, 19 Jun 2026 19:10:36 +0000 Subject: [PATCH 2/2] 8386798: Shenandoah: Missing load barrier when making assertions about mark bitmap Reviewed-by: xpeng, kdnilsen --- .../share/gc/shenandoah/shenandoahAsserts.cpp | 10 ++++++++++ .../share/gc/shenandoah/shenandoahAsserts.hpp | 7 +++++++ .../share/gc/shenandoah/shenandoahFreeSet.cpp | 12 +++++------- .../gc/shenandoah/shenandoahHeapRegion.cpp | 17 ++--------------- .../gc/shenandoah/shenandoahMarkingContext.cpp | 6 ++++-- 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp index ad00ab2ada9..34b4f235a00 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp @@ -30,6 +30,7 @@ #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "memory/resourceArea.hpp" +#include "runtime/orderAccess.hpp" void print_raw_memory(ShenandoahMessageBuffer &msg, void* loc) { // Be extra safe. Only access data that is guaranteed to be safe: @@ -381,6 +382,15 @@ void ShenandoahAsserts::assert_marked_strong(void *interior_loc, oop obj, const } } +void ShenandoahAsserts::assert_bitmap_clear_above_top(ShenandoahHeapRegion* region) { + ShenandoahMarkingContext* const ctx = ShenandoahHeap::heap()->marking_context(); + const HeapWord* top_bitmap = ctx->top_bitmap(region); + // Make sure that top is loaded before any of the marks from the bitmap are loaded. If another + // thread has cleared the bitmap we must not allow any stale reads. + OrderAccess::loadload(); + assert(ctx->is_bitmap_range_within_region_clear(top_bitmap, region->end()), "Bitmap above top_bitmap() must be clear"); +} + void ShenandoahAsserts::assert_in_cset(void* interior_loc, oop obj, const char* file, int line) { assert_correct(interior_loc, obj, file, line); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp index 31a99bf438c..2d34c797566 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp @@ -30,6 +30,8 @@ #include "runtime/mutex.hpp" #include "utilities/formatBuffer.hpp" +class ShenandoahHeapRegion; + typedef FormatBuffer<8192> ShenandoahMessageBuffer; class ShenandoahAsserts { @@ -64,6 +66,7 @@ class ShenandoahAsserts { static void assert_marked(void* interior_loc, oop obj, const char* file, int line); static void assert_marked_weak(void* interior_loc, oop obj, const char* file, int line); static void assert_marked_strong(void* interior_loc, oop obj, const char* file, int line); + static void assert_bitmap_clear_above_top(ShenandoahHeapRegion* region); static void assert_in_cset(void* interior_loc, oop obj, const char* file, int line); static void assert_not_in_cset(void* interior_loc, oop obj, const char* file, int line); static void assert_not_in_cset_loc(void* interior_loc, const char* file, int line); @@ -127,6 +130,9 @@ class ShenandoahAsserts { #define shenandoah_assert_marked_strong(interior_loc, obj) \ ShenandoahAsserts::assert_marked_strong(interior_loc, obj, __FILE__, __LINE__) +#define shenandoah_assert_clear_above_top(region) \ + ShenandoahAsserts::assert_bitmap_clear_above_top(region) + #define shenandoah_assert_in_cset_if(interior_loc, obj, condition) \ if (condition) ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__) #define shenandoah_assert_in_cset_except(interior_loc, obj, exception) \ @@ -211,6 +217,7 @@ class ShenandoahAsserts { #define shenandoah_assert_marked_strong_except(interior_loc, obj, exception) #define shenandoah_assert_marked_strong(interior_loc, obj) +#define shenandoah_assert_clear_above_top(region) #define shenandoah_assert_in_cset_if(interior_loc, obj, condition) #define shenandoah_assert_in_cset_except(interior_loc, obj, exception) #define shenandoah_assert_in_cset(interior_loc, obj) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 87c4943b238..d32e940d646 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2016, 2021, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,6 @@ #include "gc/shenandoah/shenandoahYoungGeneration.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" -#include "runtime/orderAccess.hpp" static const char* partition_name(ShenandoahFreeSetPartitionId t) { switch (t) { @@ -1049,11 +1048,10 @@ HeapWord* ShenandoahFreeSet::try_allocate_in(ShenandoahHeapRegion* r, Shenandoah } _heap->generation_for(r->affiliation())->increment_affiliated_region_count(); -#ifdef ASSERT - ShenandoahMarkingContext* const ctx = _heap->marking_context(); - assert(ctx->top_at_mark_start(r) == r->bottom(), "Newly established allocation region starts with TAMS equal to bottom"); - assert(ctx->is_bitmap_range_within_region_clear(ctx->top_bitmap(r), r->end()), "Bitmap above top_bitmap() must be clear"); -#endif + + assert(_heap->marking_context()->top_at_mark_start(r) == r->bottom(), + "Newly established allocation region (%zu) must start with TAMS equal to bottom", r->index()); + shenandoah_assert_clear_above_top(r); log_debug(gc, free)("Using new region (%zu) for %s (" PTR_FORMAT ").", r->index(), ShenandoahAllocRequest::alloc_type_to_string(req.type()), p2i(&req)); } else { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index 2736376fe9a..39f25194a6d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2020, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -32,7 +32,6 @@ #include "gc/shenandoah/shenandoahGeneration.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" -#include "gc/shenandoah/shenandoahHeapRegionSet.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" #include "gc/shenandoah/shenandoahOldGeneration.hpp" #include "gc/shenandoah/shenandoahScanRemembered.inline.hpp" @@ -40,15 +39,12 @@ #include "jfr/jfrEvents.hpp" #include "memory/allocation.hpp" #include "memory/iterator.inline.hpp" -#include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/globals_extension.hpp" #include "runtime/java.hpp" -#include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" -#include "runtime/safepoint.hpp" #include "utilities/powerOfTwo.hpp" size_t ShenandoahHeapRegion::RegionCount = 0; @@ -863,16 +859,7 @@ void ShenandoahHeapRegion::set_affiliation(ShenandoahAffiliation new_affiliation p2i(top()), p2i(ctx->top_at_mark_start(this)), p2i(_update_watermark), p2i(ctx->top_bitmap(this))); } -#ifdef ASSERT - { - size_t idx = this->index(); - HeapWord* top_bitmap = ctx->top_bitmap(this); - - assert(ctx->is_bitmap_range_within_region_clear(top_bitmap, _end), - "Region %zu, bitmap should be clear between top_bitmap: " PTR_FORMAT " and end: " PTR_FORMAT, idx, - p2i(top_bitmap), p2i(_end)); - } -#endif + shenandoah_assert_clear_above_top(this); if (region_affiliation == new_affiliation) { return; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp index 0bcdfa9fd2c..87629cefb0d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2018, 2026, Red Hat, Inc. All rights reserved. + * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved. * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,6 +91,8 @@ void ShenandoahMarkingContext::clear_bitmap(ShenandoahHeapRegion* r) { if (top_bitmap > bottom) { _mark_bit_map.clear_range_large(MemRegion(bottom, top_bitmap)); + // All bitmap writes must complete before we update top at bitmap. If these writes were reordered, + // other threads could see stale marks above top, which is not valid. OrderAccess::storestore(); _top_bitmaps[r->index()] = bottom; }