-
Bug
-
Resolution: Unresolved
-
P3
-
None
-
25
There are some scenarios in which GenShen may have improper remembered set verification logic:
1. Concurrent young cycles following a Full GC:
In the end of ShenandoahFullGC, it reset bitmap for the entire heap w/o resetting marking context to be incomplete, but ShenandoahVerifier has code like below to get a complete old marking context for remembered set verification
```
ShenandoahVerifier
ShenandoahMarkingContext* ShenandoahVerifier::get_marking_context_for_old() {
shenandoah_assert_generations_reconciled();
if (_heap->old_generation()->is_mark_complete() || _heap->gc_generation()->is_global()) {
return _heap->complete_marking_context();
}
return nullptr;
}
```
For the concurrent young GC cycles after a full GC, the old marking context used for remembered set verification is stale, and may cause unexpected result.
2. For the impl of `ShenandoahVerifier::get_marking_context_for_old` mentioned above, it always return a marking context for global GC, but marking bitmaps is already reset before before init-mark, `ShenandoahVerifier::help_verify_region_rem_set` always skip verification in this case.
3. ShenandoahConcurrentGC always clean remembered set read table, but only swap read/write table when gc generation is young, this issue causes remembered set verification before init-mark to use a completely clean remembered set, but this issue itself is covered by issue #2.
4. After concurrent young cycle evacuates objects from a young region, it update refs using marking bitmaps from marking context, therefore it won't update references of dead old objects(is_marked(obj) is false: obj is not marking strong/weak and it is below tams). In this case, if the next cycle if global concurrent GC, remembered set can't be verified before init-mark because of the dead pointers, because marking context of old will be reset before rem-set verification, rem-set verifier will scan old gen w/o using marking context and may reach the dead object with dead pointers.
1. Concurrent young cycles following a Full GC:
In the end of ShenandoahFullGC, it reset bitmap for the entire heap w/o resetting marking context to be incomplete, but ShenandoahVerifier has code like below to get a complete old marking context for remembered set verification
```
ShenandoahVerifier
ShenandoahMarkingContext* ShenandoahVerifier::get_marking_context_for_old() {
shenandoah_assert_generations_reconciled();
if (_heap->old_generation()->is_mark_complete() || _heap->gc_generation()->is_global()) {
return _heap->complete_marking_context();
}
return nullptr;
}
```
For the concurrent young GC cycles after a full GC, the old marking context used for remembered set verification is stale, and may cause unexpected result.
2. For the impl of `ShenandoahVerifier::get_marking_context_for_old` mentioned above, it always return a marking context for global GC, but marking bitmaps is already reset before before init-mark, `ShenandoahVerifier::help_verify_region_rem_set` always skip verification in this case.
3. ShenandoahConcurrentGC always clean remembered set read table, but only swap read/write table when gc generation is young, this issue causes remembered set verification before init-mark to use a completely clean remembered set, but this issue itself is covered by issue #2.
4. After concurrent young cycle evacuates objects from a young region, it update refs using marking bitmaps from marking context, therefore it won't update references of dead old objects(is_marked(obj) is false: obj is not marking strong/weak and it is below tams). In this case, if the next cycle if global concurrent GC, remembered set can't be verified before init-mark because of the dead pointers, because marking context of old will be reset before rem-set verification, rem-set verifier will scan old gen w/o using marking context and may reach the dead object with dead pointers.
- links to
-
Review(master) openjdk/jdk/24092