RFR: 8373116: Genshen: arraycopy_work should be done unconditionally by arraycopy_marking if the array is in an old region [v5]

William Kemper wkemper at openjdk.org
Fri Dec 5 23:23:00 UTC 2025


On Fri, 5 Dec 2025 18:19:39 GMT, Xiaolong Peng <xpeng at openjdk.org> wrote:

>> Chasing the root cause of JDK-8372498, I have narrowed down root cause to the commit https://github.com/openjdk/jdk/commit/f8cf9ca69cfef286c80559bfe1d147b6303d10d2
>> 
>> It is caused by the behavior change from follow code:
>> 
>> Original:
>> 
>>   if (ShenandoahSATBBarrier) {
>>     T* array = dst;
>>     HeapWord* array_addr = reinterpret_cast<HeapWord*>(array);
>>     ShenandoahHeapRegion* r = _heap->heap_region_containing(array_addr);
>>     if (is_old_marking) {
>>       // Generational, old marking
>>       assert(_heap->mode()->is_generational(), "Invariant");
>>       if (r->is_old() && (array_addr < _heap->marking_context()->top_at_mark_start(r))) {
>>         arraycopy_work<T, false, false, true>(array, count);
>>       }
>>     } else if (_heap->mode()->is_generational()) {
>>       // Generational, young marking
>>       if (r->is_old() || (array_addr < _heap->marking_context()->top_at_mark_start(r))) {
>>         arraycopy_work<T, false, false, true>(array, count);
>>       }
>>     } else if (array_addr < _heap->marking_context()->top_at_mark_start(r)) {
>>       // Non-generational, marking
>>       arraycopy_work<T, false, false, true>(array, count);
>>     }
>>   }
>> 
>> New:
>> 
>>   if (ShenandoahSATBBarrier) {
>>     if (!_heap->marking_context()->allocated_after_mark_start(reinterpret_cast<HeapWord*>(dst))) {
>>       arraycopy_work<T, false, false, true>(dst, count);
>>     }
>>   }
>> 
>> 
>> 
>> With the new STAB barrier code for arraycopy_marking, if is it young GC and the array is in old region, but array is above TAMS, arraycopy_work won't be applied anymore, so we may have missed some pointers in SATB in such case.
>> 
>> ### Test
>> - [x] hotspot_gc_shenandoah
>> - [x] repeat gc/TestAllocHumongousFragment.java#generational and sure it won't crash with the fix
>> - [x] GHA
>
> Xiaolong Peng has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Add include header shenandoahOldGeneration.hpp

At step 2, we have an element in the old array pointing to young, correct? Why is it not represented in the remembered set at the beginning of young mark? If it is because the old -> young pointer was created _after_ init mark, then the young pointer was either reachable when mark started, or it was created after mark started. Either way, the young pointer should have been found without this SATB modification. Unless, it was in the remembered set, but it didn't get scanned because a mutator modified it before it was scanned.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/28669#issuecomment-3618939846


More information about the shenandoah-dev mailing list