Skip to content
Permalink
Browse files
8234534: Simplify CardTable code after CMS removal
Reviewed-by: ayang, kbarrett
  • Loading branch information
Thomas Schatzl committed Feb 5, 2021
1 parent ee2f205 commit 78b0d3274200df6ad1063f26ce637c163dbd6ac8
@@ -556,8 +556,6 @@ void DefNewGeneration::collect(bool full,
// The preserved marks should be empty at the start of the GC.
_preserved_marks_set.init(1);

heap->rem_set()->prepare_for_younger_refs_iterate(false);

assert(heap->no_allocs_since_save_marks(),
"save marks have not been newly set.");

@@ -61,8 +61,7 @@ inline void DefNewGeneration::KeepAliveClosure::do_oop_work(T* p) {
// dirty cards in the young gen are never scanned, so the
// extra check probably isn't worthwhile.
if (GenCollectedHeap::heap()->is_in_reserved(p)) {
oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
_rs->inline_write_ref_field_gc(p, obj);
_rs->inline_write_ref_field_gc(p);
}
}

@@ -84,7 +83,7 @@ inline void DefNewGeneration::FastKeepAliveClosure::do_oop_work(T* p) {
// generation pointer.
oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
if ((cast_from_oop<HeapWord*>(obj) < _boundary) && GenCollectedHeap::heap()->is_in_reserved(p)) {
_rs->inline_write_ref_field_gc(p, obj);
_rs->inline_write_ref_field_gc(p);
}
}

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -97,6 +97,5 @@ void SerialHeap::young_process_roots(OopIterateClosure* root_closure,
process_roots(SO_ScavengeCodeCache, root_closure,
cld_closure, cld_closure, &mark_code_closure);

rem_set()->at_younger_refs_iterate();
old_gen()->younger_refs_iterate(old_gen_closure);
}
@@ -121,7 +121,7 @@ void CardTableBarrierSetC2::post_barrier(GraphKit* kit,
}

// Smash zero into card
if(!ct->scanned_concurrently()) {
if (!ct->scanned_concurrently()) {
__ store(__ ctrl(), card_adr, zero, T_BYTE, adr_type, MemNode::unordered);
} else {
// Specialized path for CM store barrier
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -309,7 +309,7 @@ void CardGeneration::space_iterate(SpaceClosure* blk,

void CardGeneration::younger_refs_iterate(OopIterateClosure* blk) {
// Apply "cl->do_oop" to (the address of) (exactly) all the ref fields in
// "sp" that point into younger generations.
// "sp" that point into the young generation.
// The iteration is only over objects allocated at the start of the
// iterations; objects allocated as a result of applying the closure are
// not included.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,53 +38,8 @@
#include "runtime/os.hpp"
#include "utilities/macros.hpp"

CardTable::CardValue CardTableRS::find_unused_youngergenP_card_value() {
for (CardValue v = youngergenP1_card;
v < cur_youngergen_and_prev_nonclean_card;
v++) {
bool seen = false;
for (int g = 0; g < _regions_to_iterate; g++) {
if (_last_cur_val_in_gen[g] == v) {
seen = true;
break;
}
}
if (!seen) {
return v;
}
}
ShouldNotReachHere();
return 0;
}

void CardTableRS::prepare_for_younger_refs_iterate(bool parallel) {
// Parallel or sequential, we must always set the prev to equal the
// last one written.
if (parallel) {
// Find a parallel value to be used next.
jbyte next_val = find_unused_youngergenP_card_value();
set_cur_youngergen_card_val(next_val);

} else {
// In an sequential traversal we will always write youngergen, so that
// the inline barrier is correct.
set_cur_youngergen_card_val(youngergen_card);
}
}

void CardTableRS::at_younger_refs_iterate() {
// The indexing in this array is slightly odd. We want to access
// the old generation record here, which is at index 2.
_last_cur_val_in_gen[2] = cur_youngergen_card_val();
}

inline bool ClearNoncleanCardWrapper::clear_card(CardValue* entry) {
CardValue entry_val = *entry;
assert(entry_val != CardTableRS::clean_card_val(),
"We shouldn't be looking at clean cards, and this should "
"be the only place they get cleaned.");
assert(entry_val != CardTableRS::cur_youngergen_and_prev_nonclean_card,
"This should be possible in the sequential case.");
assert(*entry == CardTableRS::dirty_card_val(), "Only look at dirty cards.");
*entry = CardTableRS::clean_card_val();
return true;
}
@@ -480,58 +435,10 @@ void CardTableRS::verify() {
}

CardTableRS::CardTableRS(MemRegion whole_heap, bool scanned_concurrently) :
CardTable(whole_heap, scanned_concurrently),
_cur_youngergen_card_val(youngergenP1_card),
// LNC functionality
_lowest_non_clean(NULL),
_lowest_non_clean_chunk_size(NULL),
_lowest_non_clean_base_chunk_index(NULL),
_last_LNC_resizing_collection(NULL)
{
// max_gens is really GenCollectedHeap::heap()->gen_policy()->number_of_generations()
// (which is always 2, young & old), but GenCollectedHeap has not been initialized yet.
uint max_gens = 2;
_last_cur_val_in_gen = NEW_C_HEAP_ARRAY(CardValue, max_gens + 1, mtGC);
for (uint i = 0; i < max_gens + 1; i++) {
_last_cur_val_in_gen[i] = clean_card_val();
}
}

CardTableRS::~CardTableRS() {
FREE_C_HEAP_ARRAY(CardValue, _last_cur_val_in_gen);
FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean);
FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size);
FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index);
FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection);
}
CardTable(whole_heap, scanned_concurrently) { }

void CardTableRS::initialize() {
CardTable::initialize();
_lowest_non_clean =
NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC);
_lowest_non_clean_chunk_size =
NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC);
_lowest_non_clean_base_chunk_index =
NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC);
_last_LNC_resizing_collection =
NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC);

for (int i = 0; i < _max_covered_regions; i++) {
_lowest_non_clean[i] = NULL;
_lowest_non_clean_chunk_size[i] = 0;
_last_LNC_resizing_collection[i] = -1;
}
}

bool CardTableRS::card_will_be_scanned(CardValue cv) {
return card_is_dirty_wrt_gen_iter(cv) || is_prev_nonclean_card_val(cv);
}

bool CardTableRS::card_may_have_been_dirty(CardValue cv) {
return
cv != clean_card &&
(card_is_dirty_wrt_gen_iter(cv) ||
CardTableRS::youngergen_may_have_been_dirty(cv));
}

void CardTableRS::non_clean_card_iterate(Space* sp,
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,74 +36,24 @@ class Space;
// This RemSet uses a card table both as shared data structure
// for a mod ref barrier set and for the rem set information.

class CardTableRS: public CardTable {
class CardTableRS : public CardTable {
friend class VMStructs;
// Below are private classes used in impl.
friend class VerifyCTSpaceClosure;
friend class ClearNoncleanCardWrapper;

void verify_space(Space* s, HeapWord* gen_start);

enum ExtendedCardValue {
youngergen_card = CT_MR_BS_last_reserved + 1,
// These are for parallel collection.
// There are three P (parallel) youngergen card values. In general, this
// needs to be more than the number of generations (including the perm
// gen) that might have younger_refs_do invoked on them separately. So
// if we add more gens, we have to add more values.
youngergenP1_card = CT_MR_BS_last_reserved + 2,
youngergenP2_card = CT_MR_BS_last_reserved + 3,
youngergenP3_card = CT_MR_BS_last_reserved + 4,
cur_youngergen_and_prev_nonclean_card =
CT_MR_BS_last_reserved + 5
};

// An array that contains, for each generation, the card table value last
// used as the current value for a younger_refs_do iteration of that
// portion of the table. The perm gen is index 0. The young gen is index 1,
// but will always have the value "clean_card". The old gen is index 2.
CardValue* _last_cur_val_in_gen;

CardValue _cur_youngergen_card_val;

// Number of generations, plus one for lingering PermGen issues in CardTableRS.
static const int _regions_to_iterate = 3;

CardValue cur_youngergen_card_val() {
return _cur_youngergen_card_val;
}
void set_cur_youngergen_card_val(CardValue v) {
_cur_youngergen_card_val = v;
}
bool is_prev_youngergen_card_val(CardValue v) {
return
youngergen_card <= v &&
v < cur_youngergen_and_prev_nonclean_card &&
v != _cur_youngergen_card_val;
}
// Return a youngergen_card_value that is not currently in use.
CardValue find_unused_youngergenP_card_value();

public:
CardTableRS(MemRegion whole_heap, bool scanned_concurrently);
~CardTableRS();

void younger_refs_in_space_iterate(Space* sp, HeapWord* gen_boundary, OopIterateClosure* cl);

virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN;

// Override.
void prepare_for_younger_refs_iterate(bool parallel);

// Card table entries are cleared before application;
void at_younger_refs_iterate();

void inline_write_ref_field_gc(void* field, oop new_val) {
void inline_write_ref_field_gc(void* field) {
CardValue* byte = byte_for(field);
*byte = youngergen_card;
}
void write_ref_field_gc_work(void* field, oop new_val) {
inline_write_ref_field_gc(field, new_val);
*byte = dirty_card_val();
}

bool is_aligned(HeapWord* addr) {
@@ -117,33 +67,6 @@ class CardTableRS: public CardTable {

void invalidate_or_clear(Generation* old_gen);

bool is_prev_nonclean_card_val(CardValue v) {
return
youngergen_card <= v &&
v <= cur_youngergen_and_prev_nonclean_card &&
v != _cur_youngergen_card_val;
}

static bool youngergen_may_have_been_dirty(CardValue cv) {
return cv == CardTableRS::cur_youngergen_and_prev_nonclean_card;
}

// *** Support for parallel card scanning.

// dirty and precleaned are equivalent wrt younger_refs_iter.
static bool card_is_dirty_wrt_gen_iter(CardValue cv) {
return cv == dirty_card;
}

// Returns "true" iff the value "cv" will cause the card containing it
// to be scanned in the current traversal. May be overridden by
// subtypes.
bool card_will_be_scanned(CardValue cv);

// Returns "true" iff the value "cv" may have represented a dirty card at
// some point.
bool card_may_have_been_dirty(CardValue cv);

// 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
// of mr. Clears the dirty cards as they are processed.
@@ -153,18 +76,6 @@ class CardTableRS: public CardTable {
OopIterateClosure* cl,
CardTableRS* ct);

// This is an array, one element per covered region of the card table.
// Each entry is itself an array, with one element per chunk in the
// covered region. Each entry of these arrays is the lowest non-clean
// card of the corresponding chunk containing part of an object from the
// previous chunk, or else NULL.
typedef CardValue* CardPtr;
typedef CardPtr* CardArr;
CardArr* _lowest_non_clean;
size_t* _lowest_non_clean_chunk_size;
uintptr_t* _lowest_non_clean_base_chunk_index;
volatile int* _last_LNC_resizing_collection;

virtual bool is_in_young(oop obj) const;
};

@@ -179,9 +90,6 @@ class ClearNoncleanCardWrapper: public MemRegionClosure {
// Clears the given card, return true if the corresponding card should be
// processed.
inline bool clear_card(CardValue* entry);
// Work methods called by the clear_card()
inline bool clear_card_serial(CardValue* entry);
inline bool clear_card_parallel(CardValue* entry);
// check alignment of pointer
bool is_word_aligned(CardValue* entry);

@@ -82,7 +82,7 @@ void DefNewYoungerGenClosure::barrier(T* p) {
oop obj = CompressedOops::decode_not_null(heap_oop);
// If p points to a younger generation, mark the card.
if (cast_from_oop<HeapWord*>(obj) < _old_gen_start) {
_rs->inline_write_ref_field_gc(p, obj);
_rs->inline_write_ref_field_gc(p);
}
}

@@ -279,8 +279,6 @@
declare_constant(CardTable::card_size) \
declare_constant(CardTable::card_size_in_words) \
\
declare_constant(CardTableRS::youngergen_card) \
\
declare_constant(CollectedHeap::Serial) \
declare_constant(CollectedHeap::Parallel) \
declare_constant(CollectedHeap::G1) \

0 comments on commit 78b0d32

Please sign in to comment.