8234534: Simplify CardTable code after CMS removal
Reviewed-by: ayang, kbarrett
This commit is contained in:
parent
ee2f205529
commit
78b0d32742
@ -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,7 +36,7 @@ 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;
|
||||
@ -44,66 +44,16 @@ class CardTableRS: public CardTable {
|
||||
|
||||
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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
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 @@ private:
|
||||
// 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) \
|
||||
|
Loading…
x
Reference in New Issue
Block a user