Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JDK-8267562: G1: Missing BOT in Open Archive regions causes long pauses #4265

Closed
wants to merge 3 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -2047,6 +2047,16 @@ void FileMapInfo::fixup_mapped_heap_regions() {
assert(open_archive_heap_ranges != NULL, "NULL open_archive_heap_ranges array with non-zero count");
G1CollectedHeap::heap()->fill_archive_regions(open_archive_heap_ranges,
num_open_archive_heap_ranges);

// Populate the open archive regions' G1BlockOffsetTableParts. That ensures
// fast G1BlockOffsetTablePart::block_start operations for any given address
// within the open archive regions when trying to find start of an object
// (e.g. during card table scanning).
//
// This is only needed for open archive regions, but not the closed archive
// regions, because objects in closed archive regions are 'immutable'.
Copy link
Contributor

@tschatzl tschatzl Jun 1, 2021

Choose a reason for hiding this comment

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

Suggested change
// This is only needed for open archive regions, but not the closed archive
// regions, because objects in closed archive regions are 'immutable'.
// This is only needed for open archive regions, but not the closed archive
// regions, because objects in closed archive regions never reference objects
// outside the closed archive regions and they are immutable, so we never
// need their BOT during garbage collection.

G1CollectedHeap::heap()->populate_archive_regions_bot_part(open_archive_heap_ranges,
num_open_archive_heap_ranges);
}
}

@@ -82,6 +82,19 @@ G1BlockOffsetTablePart::G1BlockOffsetTablePart(G1BlockOffsetTable* array, HeapRe
{
}

void G1BlockOffsetTablePart::update() {
HeapWord* next_addr = _hr->bottom();
HeapWord* const limit = _hr->top();

HeapWord* prev_addr;
while (next_addr < limit) {
prev_addr = next_addr;
next_addr = prev_addr + block_size(prev_addr);
alloc_block(prev_addr, next_addr);
}
assert(next_addr == limit, "Should stop the scan at the limit.");
}

// The arguments follow the normal convention of denoting
// a right-open interval: [start, end)
void G1BlockOffsetTablePart:: set_remainder_to_point_to_start(HeapWord* start, HeapWord* end) {
@@ -185,6 +185,8 @@ class G1BlockOffsetTablePart {
// The elements of the array are initialized to zero.
G1BlockOffsetTablePart(G1BlockOffsetTable* array, HeapRegion* hr);

void update();

void verify() const;

// Returns the address of the start of the block containing "addr", or
@@ -712,6 +712,27 @@ inline HeapWord* G1CollectedHeap::attempt_allocation(size_t min_word_size,
return result;
}

void G1CollectedHeap::populate_archive_regions_bot_part(MemRegion* ranges, size_t count) {
assert(!is_init_completed(), "Expect to be called at JVM init time");
assert(ranges != NULL, "MemRegion array NULL");
assert(count != 0, "No MemRegions provided");

HeapWord* st = ranges[0].start();
HeapWord* last = ranges[count-1].last();
HeapRegion* hr_st = _hrm.addr_to_region(st);
HeapRegion* hr_last = _hrm.addr_to_region(last);

HeapRegion* hr_curr = hr_st;
while (hr_curr != NULL) {
hr_curr->update_bot();
if (hr_curr != hr_last) {
hr_curr = _hrm.next_region_in_heap(hr_curr);
} else {
hr_curr = NULL;
}
}
}

void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
assert(!is_init_completed(), "Expect to be called at JVM init time");
assert(ranges != NULL, "MemRegion array NULL");
@@ -740,6 +740,10 @@ class G1CollectedHeap : public CollectedHeap {
// alloc_archive_regions, and after class loading has occurred.
void fill_archive_regions(MemRegion* range, size_t count);

// Populate the G1BlockOffsetTablePart for archived regions with the given
// memory ranges.
void populate_archive_regions_bot_part(MemRegion* range, size_t count);

// For each of the specified MemRegions, uncommit the containing G1 regions
// which had been allocated by alloc_archive_regions. This should be called
// rather than fill_archive_regions at JVM init time if the archive file
@@ -84,7 +84,7 @@ bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion*
// lack BOT information for performance reasons.
// Recreate BOT information of high live ratio young regions here to keep expected
// performance during scanning their card tables in the collection pauses later.
update_bot(hr);
hr->update_bot();
}
log_trace(gc, phases)("Phase 2: skip compaction region index: %u, live words: " SIZE_FORMAT,
hr->hrm_index(), _collector->live_words(hr->hrm_index()));
@@ -146,22 +146,6 @@ bool G1FullGCPrepareTask::G1CalculatePointersClosure::should_compact(HeapRegion*
return live_words <= live_words_threshold;
}

void G1FullGCPrepareTask::G1CalculatePointersClosure::update_bot(HeapRegion* hr) {
HeapWord* const limit = hr->top();
HeapWord* next_addr = hr->bottom();
HeapWord* threshold = hr->initialize_threshold();
HeapWord* prev_addr;
while (next_addr < limit) {
prev_addr = next_addr;
next_addr = _bitmap->get_next_marked_addr(next_addr + 1, limit);

if (next_addr > threshold) {
threshold = hr->cross_threshold(prev_addr, next_addr);
}
}
assert(next_addr == limit, "Should stop the scan at the limit.");
}

void G1FullGCPrepareTask::G1CalculatePointersClosure::reset_region_metadata(HeapRegion* hr) {
hr->rem_set()->clear();
hr->clear_cardtable();
@@ -63,7 +63,6 @@ class G1FullGCPrepareTask : public G1FullGCTask {
bool should_compact(HeapRegion* hr);
void prepare_for_compaction(HeapRegion* hr);
void prepare_for_compaction_work(G1FullGCCompactionPoint* cp, HeapRegion* hr);
void update_bot(HeapRegion* hr);

void reset_region_metadata(HeapRegion* hr);

@@ -194,6 +194,10 @@ class HeapRegion : public CHeapObj<mtGC> {
_bot_part.reset_bot();
}

void update_bot() {
_bot_part.update();
}

private:
// The remembered set for this region.
HeapRegionRemSet* _rem_set;