Skip to content

Commit

Permalink
8304412: Serial: Refactor old generation cards update after Full GC
Browse files Browse the repository at this point in the history
Reviewed-by: tschatzl, kbarrett
  • Loading branch information
albertnetymk committed Mar 28, 2023
1 parent 3c4cd50 commit 7987ad4
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 45 deletions.
40 changes: 14 additions & 26 deletions src/hotspot/share/gc/serial/cardTableRS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions src/hotspot/share/gc/serial/cardTableRS.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,11 @@ class CardTableRS : public CardTable {

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
Expand Down
18 changes: 2 additions & 16 deletions src/hotspot/share/gc/serial/genMarkSweep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down

1 comment on commit 7987ad4

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.