8367709: GenShen: Dirty cards for objects that get promoted by safepoint that intervenes between allocation and stores

Reviewed-by: ysr
This commit is contained in:
William Kemper 2025-10-16 17:49:08 +00:00
parent 844118a9d8
commit d4472979c4
5 changed files with 25 additions and 14 deletions

View File

@ -89,8 +89,19 @@ bool ShenandoahBarrierSet::need_keep_alive_barrier(DecoratorSet decorators, Basi
void ShenandoahBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {
#if COMPILER2_OR_JVMCI
assert(!ReduceInitialCardMarks || !ShenandoahCardBarrier || ShenandoahGenerationalHeap::heap()->is_in_young(new_obj),
"Allocating new object outside of young generation: " INTPTR_FORMAT, p2i(new_obj));
if (ReduceInitialCardMarks && ShenandoahCardBarrier && !ShenandoahHeap::heap()->is_in_young(new_obj)) {
log_debug(gc)("Newly allocated object (" PTR_FORMAT ") is not in the young generation", p2i(new_obj));
// This can happen when an object is newly allocated, but we come to a safepoint before returning
// the object. If the safepoint runs a degenerated cycle that is upgraded to a full GC, this object
// will have survived two GC cycles. If the tenuring age is very low (1), this object may be promoted.
// In this case, we have an allocated object, but it has received no stores yet. If card marking barriers
// have been elided, we could end up with an object in old holding pointers to young that won't be in
// the remembered set. The solution here is conservative, but this problem should be rare, and it will
// correct itself on subsequent cycles when the remembered set is updated.
ShenandoahGenerationalHeap::heap()->old_generation()->card_scan()->mark_range_as_dirty(
cast_from_oop<HeapWord*>(new_obj), new_obj->size()
);
}
#endif // COMPILER2_OR_JVMCI
assert(thread->deferred_card_mark().is_empty(), "We don't use this");
}

View File

@ -74,8 +74,8 @@ void ShenandoahMarkingContext::initialize_top_at_mark_start(ShenandoahHeapRegion
_top_at_mark_starts_base[idx] = bottom;
_top_bitmaps[idx] = bottom;
log_debug(gc)("SMC:initialize_top_at_mark_start for Region %zu, TAMS: " PTR_FORMAT ", TopOfBitMap: " PTR_FORMAT,
r->index(), p2i(bottom), p2i(r->end()));
log_debug(gc, mark)("SMC:initialize_top_at_mark_start for Region %zu, TAMS: " PTR_FORMAT ", TopOfBitMap: " PTR_FORMAT,
r->index(), p2i(bottom), p2i(r->end()));
}
HeapWord* ShenandoahMarkingContext::top_bitmap(ShenandoahHeapRegion* r) {
@ -86,8 +86,8 @@ void ShenandoahMarkingContext::clear_bitmap(ShenandoahHeapRegion* r) {
HeapWord* bottom = r->bottom();
HeapWord* top_bitmap = _top_bitmaps[r->index()];
log_debug(gc)("SMC:clear_bitmap for %s Region %zu, top_bitmap: " PTR_FORMAT,
r->affiliation_name(), r->index(), p2i(top_bitmap));
log_debug(gc, mark)("SMC:clear_bitmap for %s Region %zu, top_bitmap: " PTR_FORMAT,
r->affiliation_name(), r->index(), p2i(top_bitmap));
if (top_bitmap > bottom) {
_mark_bit_map.clear_range_large(MemRegion(bottom, top_bitmap));

View File

@ -104,8 +104,8 @@ inline void ShenandoahMarkingContext::capture_top_at_mark_start(ShenandoahHeapRe
"Region %zu, bitmap should be clear while adjusting TAMS: " PTR_FORMAT " -> " PTR_FORMAT,
idx, p2i(old_tams), p2i(new_tams));
log_debug(gc)("Capturing TAMS for %s Region %zu, was: " PTR_FORMAT ", now: " PTR_FORMAT,
r->affiliation_name(), idx, p2i(old_tams), p2i(new_tams));
log_debug(gc, mark)("Capturing TAMS for %s Region %zu, was: " PTR_FORMAT ", now: " PTR_FORMAT,
r->affiliation_name(), idx, p2i(old_tams), p2i(new_tams));
_top_at_mark_starts_base[idx] = new_tams;
_top_bitmaps[idx] = new_tams;

View File

@ -683,9 +683,9 @@ void ShenandoahScanRememberedTask::do_work(uint worker_id) {
struct ShenandoahRegionChunk assignment;
while (_work_list->next(&assignment)) {
ShenandoahHeapRegion* region = assignment._r;
log_debug(gc)("ShenandoahScanRememberedTask::do_work(%u), processing slice of region "
"%zu at offset %zu, size: %zu",
worker_id, region->index(), assignment._chunk_offset, assignment._chunk_size);
log_debug(gc, remset)("ShenandoahScanRememberedTask::do_work(%u), processing slice of region "
"%zu at offset %zu, size: %zu",
worker_id, region->index(), assignment._chunk_offset, assignment._chunk_size);
if (region->is_old()) {
size_t cluster_size =
CardTable::card_size_in_words() * ShenandoahCardCluster::CardsPerCluster;

View File

@ -343,9 +343,9 @@ ShenandoahScanRemembered::process_region_slice(ShenandoahHeapRegion *region, siz
}
}
log_debug(gc)("Remembered set scan processing Region %zu, from " PTR_FORMAT " to " PTR_FORMAT ", using %s table",
region->index(), p2i(start_of_range), p2i(end_of_range),
use_write_table? "read/write (updating)": "read (marking)");
log_debug(gc, remset)("Remembered set scan processing Region %zu, from " PTR_FORMAT " to " PTR_FORMAT ", using %s table",
region->index(), p2i(start_of_range), p2i(end_of_range),
use_write_table? "read/write (updating)": "read (marking)");
// Note that end_of_range may point to the middle of a cluster because we limit scanning to
// region->top() or region->get_update_watermark(). We avoid processing past end_of_range.