mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 10:34:38 +02:00
8071913: Filter out entries to free/uncommitted regions during iteration
Reviewed-by: sjohanss, kbarrett
This commit is contained in:
parent
adb1dcdcc2
commit
3a343a5681
7 changed files with 87 additions and 31 deletions
|
@ -1120,6 +1120,7 @@ public:
|
||||||
|
|
||||||
// Return the region with the given index. It assumes the index is valid.
|
// Return the region with the given index. It assumes the index is valid.
|
||||||
inline HeapRegion* region_at(uint index) const;
|
inline HeapRegion* region_at(uint index) const;
|
||||||
|
inline HeapRegion* region_at_or_null(uint index) const;
|
||||||
|
|
||||||
// Return the next region (by index) that is part of the same
|
// Return the next region (by index) that is part of the same
|
||||||
// humongous object that hr is part of.
|
// humongous object that hr is part of.
|
||||||
|
@ -1157,6 +1158,11 @@ public:
|
||||||
template <class T>
|
template <class T>
|
||||||
inline HeapRegion* heap_region_containing(const T addr) const;
|
inline HeapRegion* heap_region_containing(const T addr) const;
|
||||||
|
|
||||||
|
// Returns the HeapRegion that contains addr, or NULL if that is an uncommitted
|
||||||
|
// region. addr must not be NULL.
|
||||||
|
template <class T>
|
||||||
|
inline HeapRegion* heap_region_containing_or_null(const T addr) const;
|
||||||
|
|
||||||
// A CollectedHeap is divided into a dense sequence of "blocks"; that is,
|
// A CollectedHeap is divided into a dense sequence of "blocks"; that is,
|
||||||
// each address in the (reserved) heap is a member of exactly
|
// each address in the (reserved) heap is a member of exactly
|
||||||
// one block. The defining characteristic of a block is that it is
|
// one block. The defining characteristic of a block is that it is
|
||||||
|
|
|
@ -60,6 +60,9 @@ size_t G1CollectedHeap::desired_plab_sz(InCSetState dest) {
|
||||||
// Return the region with the given index. It assumes the index is valid.
|
// Return the region with the given index. It assumes the index is valid.
|
||||||
inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrm.at(index); }
|
inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrm.at(index); }
|
||||||
|
|
||||||
|
// Return the region with the given index, or NULL if unmapped. It assumes the index is valid.
|
||||||
|
inline HeapRegion* G1CollectedHeap::region_at_or_null(uint index) const { return _hrm.at_or_null(index); }
|
||||||
|
|
||||||
inline HeapRegion* G1CollectedHeap::next_region_in_humongous(HeapRegion* hr) const {
|
inline HeapRegion* G1CollectedHeap::next_region_in_humongous(HeapRegion* hr) const {
|
||||||
return _hrm.next_region_in_humongous(hr);
|
return _hrm.next_region_in_humongous(hr);
|
||||||
}
|
}
|
||||||
|
@ -84,6 +87,16 @@ inline HeapRegion* G1CollectedHeap::heap_region_containing(const T addr) const {
|
||||||
return _hrm.addr_to_region((HeapWord*) addr);
|
return _hrm.addr_to_region((HeapWord*) addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline HeapRegion* G1CollectedHeap::heap_region_containing_or_null(const T addr) const {
|
||||||
|
assert(addr != NULL, "invariant");
|
||||||
|
assert(is_in_g1_reserved((const void*) addr),
|
||||||
|
"Address " PTR_FORMAT " is outside of the heap ranging from [" PTR_FORMAT " to " PTR_FORMAT ")",
|
||||||
|
p2i((void*)addr), p2i(g1_reserved().start()), p2i(g1_reserved().end()));
|
||||||
|
uint const region_idx = addr_to_region(addr);
|
||||||
|
return region_at_or_null(region_idx);
|
||||||
|
}
|
||||||
|
|
||||||
inline void G1CollectedHeap::old_set_add(HeapRegion* hr) {
|
inline void G1CollectedHeap::old_set_add(HeapRegion* hr) {
|
||||||
_old_set.add(hr);
|
_old_set.add(hr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,10 +133,10 @@ private:
|
||||||
|
|
||||||
virtual bool do_heap_region(HeapRegion* r) {
|
virtual bool do_heap_region(HeapRegion* r) {
|
||||||
uint hrm_index = r->hrm_index();
|
uint hrm_index = r->hrm_index();
|
||||||
if (!r->in_collection_set() && r->is_old_or_humongous_or_archive()) {
|
if (!r->in_collection_set() && r->is_old_or_humongous_or_archive() && !r->is_empty()) {
|
||||||
_scan_top[hrm_index] = r->top();
|
_scan_top[hrm_index] = r->top();
|
||||||
} else {
|
} else {
|
||||||
_scan_top[hrm_index] = r->bottom();
|
_scan_top[hrm_index] = NULL;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -191,6 +191,7 @@ public:
|
||||||
void reset() {
|
void reset() {
|
||||||
for (uint i = 0; i < _max_regions; i++) {
|
for (uint i = 0; i < _max_regions; i++) {
|
||||||
_iter_states[i] = Unclaimed;
|
_iter_states[i] = Unclaimed;
|
||||||
|
_scan_top[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
G1ResetScanTopClosure cl(_scan_top);
|
G1ResetScanTopClosure cl(_scan_top);
|
||||||
|
@ -350,6 +351,10 @@ void G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
|
||||||
_scan_state->add_dirty_region(region_idx);
|
_scan_state->add_dirty_region(region_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r->rem_set()->cardset_is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We claim cards in blocks so as to reduce the contention.
|
// We claim cards in blocks so as to reduce the contention.
|
||||||
size_t const block_size = G1RSetScanBlockSize;
|
size_t const block_size = G1RSetScanBlockSize;
|
||||||
|
|
||||||
|
@ -367,18 +372,21 @@ void G1ScanRSForRegionClosure::scan_rem_set_roots(HeapRegion* r) {
|
||||||
}
|
}
|
||||||
_cards_claimed++;
|
_cards_claimed++;
|
||||||
|
|
||||||
// If the card is dirty, then G1 will scan it during Update RS.
|
HeapWord* const card_start = _g1h->bot()->address_for_index_raw(card_index);
|
||||||
if (_ct->is_card_claimed(card_index) || _ct->is_card_dirty(card_index)) {
|
uint const region_idx_for_card = _g1h->addr_to_region(card_start);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
HeapRegion* hr = _g1h->region_at_or_null(region_idx_for_card);
|
||||||
|
assert(hr == NULL || hr->is_in_reserved(card_start),
|
||||||
|
"Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
|
||||||
|
#endif
|
||||||
|
HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
|
||||||
|
if (card_start >= top) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord* const card_start = _g1h->bot()->address_for_index(card_index);
|
// If the card is dirty, then G1 will scan it during Update RS.
|
||||||
uint const region_idx_for_card = _g1h->addr_to_region(card_start);
|
if (_ct->is_card_claimed(card_index) || _ct->is_card_dirty(card_index)) {
|
||||||
|
|
||||||
assert(_g1h->region_at(region_idx_for_card)->is_in_reserved(card_start),
|
|
||||||
"Card start " PTR_FORMAT " to scan outside of region %u", p2i(card_start), _g1h->region_at(region_idx_for_card)->hrm_index());
|
|
||||||
HeapWord* const top = _scan_state->scan_top(region_idx_for_card);
|
|
||||||
if (card_start >= top) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,6 +553,16 @@ void G1RemSet::refine_card_concurrently(jbyte* card_ptr,
|
||||||
uint worker_i) {
|
uint worker_i) {
|
||||||
assert(!_g1h->is_gc_active(), "Only call concurrently");
|
assert(!_g1h->is_gc_active(), "Only call concurrently");
|
||||||
|
|
||||||
|
// Construct the region representing the card.
|
||||||
|
HeapWord* start = _ct->addr_for(card_ptr);
|
||||||
|
// And find the region containing it.
|
||||||
|
HeapRegion* r = _g1h->heap_region_containing_or_null(start);
|
||||||
|
|
||||||
|
// If this is a (stale) card into an uncommitted region, exit.
|
||||||
|
if (r == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
check_card_ptr(card_ptr, _ct);
|
check_card_ptr(card_ptr, _ct);
|
||||||
|
|
||||||
// If the card is no longer dirty, nothing to do.
|
// If the card is no longer dirty, nothing to do.
|
||||||
|
@ -552,11 +570,6 @@ void G1RemSet::refine_card_concurrently(jbyte* card_ptr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct the region representing the card.
|
|
||||||
HeapWord* start = _ct->addr_for(card_ptr);
|
|
||||||
// And find the region containing it.
|
|
||||||
HeapRegion* r = _g1h->heap_region_containing(start);
|
|
||||||
|
|
||||||
// This check is needed for some uncommon cases where we should
|
// This check is needed for some uncommon cases where we should
|
||||||
// ignore the card.
|
// ignore the card.
|
||||||
//
|
//
|
||||||
|
@ -679,6 +692,18 @@ bool G1RemSet::refine_card_during_gc(jbyte* card_ptr,
|
||||||
G1ScanObjsDuringUpdateRSClosure* update_rs_cl) {
|
G1ScanObjsDuringUpdateRSClosure* update_rs_cl) {
|
||||||
assert(_g1h->is_gc_active(), "Only call during GC");
|
assert(_g1h->is_gc_active(), "Only call during GC");
|
||||||
|
|
||||||
|
// Construct the region representing the card.
|
||||||
|
HeapWord* card_start = _ct->addr_for(card_ptr);
|
||||||
|
// And find the region containing it.
|
||||||
|
uint const card_region_idx = _g1h->addr_to_region(card_start);
|
||||||
|
|
||||||
|
HeapWord* scan_limit = _scan_state->scan_top(card_region_idx);
|
||||||
|
if (scan_limit == NULL) {
|
||||||
|
// This is a card into an uncommitted region. We need to bail out early as we
|
||||||
|
// should not access the corresponding card table entry.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
check_card_ptr(card_ptr, _ct);
|
check_card_ptr(card_ptr, _ct);
|
||||||
|
|
||||||
// If the card is no longer dirty, nothing to do. This covers cards that were already
|
// If the card is no longer dirty, nothing to do. This covers cards that were already
|
||||||
|
@ -691,13 +716,7 @@ bool G1RemSet::refine_card_during_gc(jbyte* card_ptr,
|
||||||
// number of potential duplicate scans (multiple threads may enqueue the same card twice).
|
// number of potential duplicate scans (multiple threads may enqueue the same card twice).
|
||||||
*card_ptr = G1CardTable::clean_card_val() | G1CardTable::claimed_card_val();
|
*card_ptr = G1CardTable::clean_card_val() | G1CardTable::claimed_card_val();
|
||||||
|
|
||||||
// Construct the region representing the card.
|
|
||||||
HeapWord* card_start = _ct->addr_for(card_ptr);
|
|
||||||
// And find the region containing it.
|
|
||||||
uint const card_region_idx = _g1h->addr_to_region(card_start);
|
|
||||||
|
|
||||||
_scan_state->add_dirty_region(card_region_idx);
|
_scan_state->add_dirty_region(card_region_idx);
|
||||||
HeapWord* scan_limit = _scan_state->scan_top(card_region_idx);
|
|
||||||
if (scan_limit <= card_start) {
|
if (scan_limit <= card_start) {
|
||||||
// If the card starts above the area in the region containing objects to scan, skip it.
|
// If the card starts above the area in the region containing objects to scan, skip it.
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -123,10 +123,7 @@ class HeapRegionManager: public CHeapObj<mtGC> {
|
||||||
public:
|
public:
|
||||||
bool is_free(HeapRegion* hr) const;
|
bool is_free(HeapRegion* hr) const;
|
||||||
#endif
|
#endif
|
||||||
// Returns whether the given region is available for allocation.
|
public:
|
||||||
bool is_available(uint region) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Empty constructor, we'll initialize it with the initialize() method.
|
// Empty constructor, we'll initialize it with the initialize() method.
|
||||||
HeapRegionManager();
|
HeapRegionManager();
|
||||||
|
|
||||||
|
@ -147,6 +144,13 @@ public:
|
||||||
// is valid.
|
// is valid.
|
||||||
inline HeapRegion* at(uint index) const;
|
inline HeapRegion* at(uint index) const;
|
||||||
|
|
||||||
|
// Return the HeapRegion at the given index, NULL if the index
|
||||||
|
// is for an unavailable region.
|
||||||
|
inline HeapRegion* at_or_null(uint index) const;
|
||||||
|
|
||||||
|
// Returns whether the given region is available for allocation.
|
||||||
|
bool is_available(uint region) const;
|
||||||
|
|
||||||
// Return the next region (by index) that is part of the same
|
// Return the next region (by index) that is part of the same
|
||||||
// humongous object that hr is part of.
|
// humongous object that hr is part of.
|
||||||
inline HeapRegion* next_region_in_humongous(HeapRegion* hr) const;
|
inline HeapRegion* next_region_in_humongous(HeapRegion* hr) const;
|
||||||
|
|
|
@ -47,6 +47,16 @@ inline HeapRegion* HeapRegionManager::at(uint index) const {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline HeapRegion* HeapRegionManager::at_or_null(uint index) const {
|
||||||
|
if (!is_available(index)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
HeapRegion* hr = _regions.get_by_index(index);
|
||||||
|
assert(hr != NULL, "All available regions must have a HeapRegion but index %u has not.", index);
|
||||||
|
assert(hr->hrm_index() == index, "sanity");
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
inline HeapRegion* HeapRegionManager::next_region_in_humongous(HeapRegion* hr) const {
|
inline HeapRegion* HeapRegionManager::next_region_in_humongous(HeapRegion* hr) const {
|
||||||
uint index = hr->hrm_index();
|
uint index = hr->hrm_index();
|
||||||
assert(is_available(index), "pre-condition");
|
assert(is_available(index), "pre-condition");
|
||||||
|
|
|
@ -751,7 +751,7 @@ bool HeapRegionRemSetIterator::coarse_has_next(size_t& card_index) {
|
||||||
_coarse_cur_region_cur_card = 0;
|
_coarse_cur_region_cur_card = 0;
|
||||||
HeapWord* r_bot =
|
HeapWord* r_bot =
|
||||||
_g1h->region_at((uint) _coarse_cur_region_index)->bottom();
|
_g1h->region_at((uint) _coarse_cur_region_index)->bottom();
|
||||||
_cur_region_card_offset = _bot->index_for(r_bot);
|
_cur_region_card_offset = _bot->index_for_raw(r_bot);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -792,7 +792,7 @@ void HeapRegionRemSetIterator::switch_to_prt(PerRegionTable* prt) {
|
||||||
_fine_cur_prt = prt;
|
_fine_cur_prt = prt;
|
||||||
|
|
||||||
HeapWord* r_bot = _fine_cur_prt->hr()->bottom();
|
HeapWord* r_bot = _fine_cur_prt->hr()->bottom();
|
||||||
_cur_region_card_offset = _bot->index_for(r_bot);
|
_cur_region_card_offset = _bot->index_for_raw(r_bot);
|
||||||
|
|
||||||
// The bitmap scan for the PRT always scans from _cur_region_cur_card + 1.
|
// The bitmap scan for the PRT always scans from _cur_region_cur_card + 1.
|
||||||
// To avoid special-casing this start case, and not miss the first bitmap
|
// To avoid special-casing this start case, and not miss the first bitmap
|
||||||
|
|
|
@ -187,8 +187,12 @@ public:
|
||||||
|
|
||||||
static void setup_remset_size();
|
static void setup_remset_size();
|
||||||
|
|
||||||
|
bool cardset_is_empty() const {
|
||||||
|
return _other_regions.is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
bool is_empty() const {
|
bool is_empty() const {
|
||||||
return (strong_code_roots_list_length() == 0) && _other_regions.is_empty();
|
return (strong_code_roots_list_length() == 0) && cardset_is_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool occupancy_less_or_equal_than(size_t occ) const {
|
bool occupancy_less_or_equal_than(size_t occ) const {
|
||||||
|
@ -353,7 +357,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class HeapRegionRemSetIterator : public StackObj {
|
class HeapRegionRemSetIterator : public StackObj {
|
||||||
private:
|
private:
|
||||||
// The region RSet over which we are iterating.
|
// The region RSet over which we are iterating.
|
||||||
HeapRegionRemSet* _hrrs;
|
HeapRegionRemSet* _hrrs;
|
||||||
|
|
||||||
|
@ -401,7 +405,7 @@ class HeapRegionRemSetIterator : public StackObj {
|
||||||
// The Sparse remembered set iterator.
|
// The Sparse remembered set iterator.
|
||||||
SparsePRTIter _sparse_iter;
|
SparsePRTIter _sparse_iter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HeapRegionRemSetIterator(HeapRegionRemSet* hrrs);
|
HeapRegionRemSetIterator(HeapRegionRemSet* hrrs);
|
||||||
|
|
||||||
// If there remains one or more cards to be yielded, returns true and
|
// If there remains one or more cards to be yielded, returns true and
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue