8304412: Serial: Refactor old generation cards update after Full GC

Reviewed-by: tschatzl, kbarrett
This commit is contained in:
Albert Mingkun Yang 2023-03-28 07:24:33 +00:00
parent 3c4cd50e3c
commit 7987ad427b
3 changed files with 21 additions and 45 deletions

@ -131,36 +131,24 @@ void CardTableRS::verify_used_region_at_save_marks(Space* sp) const {
}
#endif
void CardTableRS::clear_into_younger(Generation* old_gen) {
assert(GenCollectedHeap::heap()->is_old_gen(old_gen),
"Should only be called for the old generation");
// The card tables for the youngest gen need never be cleared.
// There's a bit of subtlety in the clear() and invalidate()
// methods that we exploit here and in invalidate_or_clear()
// below to avoid missing cards at the fringes. If clear() or
// invalidate() are changed in the future, this code should
// be revisited. 20040107.ysr
clear_MemRegion(old_gen->prev_used_region());
}
void CardTableRS::maintain_old_to_young_invariant(Generation* old_gen, bool is_young_gen_empty) {
assert(GenCollectedHeap::heap()->is_old_gen(old_gen), "precondition");
void CardTableRS::invalidate_or_clear(Generation* old_gen) {
assert(GenCollectedHeap::heap()->is_old_gen(old_gen),
"Should only be called for the old generation");
// Invalidate the cards for the currently occupied part of
// the old generation and clear the cards for the
// unoccupied part of the generation (if any, making use
// of that generation's prev_used_region to determine that
// region). No need to do anything for the youngest
// generation. Also see note#20040107.ysr above.
MemRegion used_mr = old_gen->used_region();
MemRegion to_be_cleared_mr = old_gen->prev_used_region().minus(used_mr);
if (!to_be_cleared_mr.is_empty()) {
clear_MemRegion(to_be_cleared_mr);
if (is_young_gen_empty) {
clear_MemRegion(old_gen->prev_used_region());
} else {
MemRegion used_mr = old_gen->used_region();
MemRegion prev_used_mr = old_gen->prev_used_region();
if (used_mr.end() < prev_used_mr.end()) {
// Shrunk; need to clear the previously-used but now-unused parts.
clear_MemRegion(MemRegion(used_mr.end(), prev_used_mr.end()));
}
// No idea which card contains old-to-young pointer, so dirtying cards for
// the entire used part of old-gen conservatively.
dirty_MemRegion(used_mr);
}
dirty_MemRegion(used_mr);
}
class VerifyCleanCardClosure: public BasicOopIterateClosure {
private:
HeapWord* _boundary;

@ -63,9 +63,11 @@ public:
void verify();
void clear_into_younger(Generation* old_gen);
void invalidate_or_clear(Generation* old_gen);
// Update old gen cards to maintain old-to-young-pointer invariant: Clear
// the old generation card table completely if the young generation had been
// completely evacuated, otherwise dirties the whole old generation to
// conservatively not loose any old-to-young pointer.
void maintain_old_to_young_invariant(Generation* old_gen, bool is_young_gen_empty);
// Iterate over the portion of the card-table which covers the given
// region mr in the given space and apply cl to any dirty sub-regions

@ -109,22 +109,8 @@ void GenMarkSweep::invoke_at_safepoint(bool clear_all_softrefs) {
MarkSweep::_string_dedup_requests->flush();
// If compaction completely evacuated the young generation then we
// can clear the card table. Otherwise, we must invalidate
// it (consider all cards dirty). In the future, we might consider doing
// compaction within generations only, and doing card-table sliding.
CardTableRS* rs = gch->rem_set();
Generation* old_gen = gch->old_gen();
// Clear/invalidate below make use of the "prev_used_regions" saved earlier.
if (gch->young_gen()->used() == 0) {
// We've evacuated the young generation.
rs->clear_into_younger(old_gen);
} else {
// Invalidate the cards corresponding to the currently used
// region and clear those corresponding to the evacuated region.
rs->invalidate_or_clear(old_gen);
}
bool is_young_gen_empty = (gch->young_gen()->used() == 0);
gch->rem_set()->maintain_old_to_young_invariant(gch->old_gen(), is_young_gen_empty);
gch->prune_scavengable_nmethods();