Skip to content

Commit 295b263

Browse files
author
Thomas Schatzl
committed
8279241: G1 Full GC does not always slide memory to bottom addresses
Reviewed-by: iwalulya, ayang, sjohanss
1 parent b327746 commit 295b263

9 files changed

+346
-209
lines changed

src/hotspot/share/gc/g1/g1FullCollector.cpp

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
3232
#include "gc/g1/g1FullGCCompactTask.hpp"
3333
#include "gc/g1/g1FullGCMarker.inline.hpp"
3434
#include "gc/g1/g1FullGCMarkTask.hpp"
35-
#include "gc/g1/g1FullGCPrepareTask.hpp"
35+
#include "gc/g1/g1FullGCPrepareTask.inline.hpp"
3636
#include "gc/g1/g1FullGCScope.hpp"
3737
#include "gc/g1/g1OopClosures.hpp"
3838
#include "gc/g1/g1Policy.hpp"
@@ -297,14 +297,67 @@ void G1FullCollector::phase1_mark_live_objects() {
297297
}
298298

299299
void G1FullCollector::phase2_prepare_compaction() {
300-
GCTraceTime(Info, gc, phases) info("Phase 2: Prepare for compaction", scope()->timer());
300+
GCTraceTime(Info, gc, phases) info("Phase 2: Prepare compaction", scope()->timer());
301+
302+
phase2a_determine_worklists();
303+
304+
bool has_free_compaction_targets = phase2b_forward_oops();
305+
306+
// Try to avoid OOM immediately after Full GC in case there are no free regions
307+
// left after determining the result locations (i.e. this phase). Prepare to
308+
// maximally compact the tail regions of the compaction queues serially.
309+
if (!has_free_compaction_targets) {
310+
phase2c_prepare_serial_compaction();
311+
}
312+
}
313+
314+
void G1FullCollector::phase2a_determine_worklists() {
315+
GCTraceTime(Debug, gc, phases) debug("Phase 2: Determine work lists", scope()->timer());
316+
317+
G1DetermineCompactionQueueClosure cl(this);
318+
_heap->heap_region_iterate(&cl);
319+
}
320+
321+
bool G1FullCollector::phase2b_forward_oops() {
322+
GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare parallel compaction", scope()->timer());
323+
301324
G1FullGCPrepareTask task(this);
302325
run_task(&task);
303326

304-
// To avoid OOM when there is memory left.
305-
if (!task.has_freed_regions()) {
306-
task.prepare_serial_compaction();
327+
return task.has_free_compaction_targets();
328+
}
329+
330+
void G1FullCollector::phase2c_prepare_serial_compaction() {
331+
GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare serial compaction", scope()->timer());
332+
// At this point we know that after parallel compaction there will be no
333+
// completely free regions. That means that the last region of
334+
// all compaction queues still have data in them. We try to compact
335+
// these regions in serial to avoid a premature OOM when the mutator wants
336+
// to allocate the first eden region after gc.
337+
for (uint i = 0; i < workers(); i++) {
338+
G1FullGCCompactionPoint* cp = compaction_point(i);
339+
if (cp->has_regions()) {
340+
serial_compaction_point()->add(cp->remove_last());
341+
}
342+
}
343+
344+
// Update the forwarding information for the regions in the serial
345+
// compaction point.
346+
G1FullGCCompactionPoint* cp = serial_compaction_point();
347+
for (GrowableArrayIterator<HeapRegion*> it = cp->regions()->begin(); it != cp->regions()->end(); ++it) {
348+
HeapRegion* current = *it;
349+
if (!cp->is_initialized()) {
350+
// Initialize the compaction point. Nothing more is needed for the first heap region
351+
// since it is already prepared for compaction.
352+
cp->initialize(current, false);
353+
} else {
354+
assert(!current->is_humongous(), "Should be no humongous regions in compaction queue");
355+
G1SerialRePrepareClosure re_prepare(cp, current);
356+
current->set_compaction_top(current->bottom());
357+
current->apply_to_marked_objects(mark_bitmap(), &re_prepare);
358+
}
307359
}
360+
cp->update();
308361
}
309362

310363
void G1FullCollector::phase3_adjust_pointers() {

src/hotspot/share/gc/g1/g1FullCollector.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -110,7 +110,7 @@ class G1FullCollector : StackObj {
110110
G1FullGCCompactionPoint* serial_compaction_point() { return &_serial_compaction_point; }
111111
G1CMBitMap* mark_bitmap();
112112
ReferenceProcessor* reference_processor();
113-
size_t live_words(uint region_index) {
113+
size_t live_words(uint region_index) const {
114114
assert(region_index < _heap->max_regions(), "sanity");
115115
return _live_stats[region_index]._live_words;
116116
}
@@ -121,13 +121,21 @@ class G1FullCollector : StackObj {
121121
inline bool is_skip_compacting(uint region_index) const;
122122
inline bool is_skip_marking(oop obj) const;
123123

124+
// Are we (potentially) going to compact into this region?
125+
inline bool is_compaction_target(uint region_index) const;
126+
124127
inline void set_free(uint region_idx);
125128
inline bool is_free(uint region_idx) const;
126129
inline void update_from_compacting_to_skip_compacting(uint region_idx);
127130

128131
private:
129132
void phase1_mark_live_objects();
130133
void phase2_prepare_compaction();
134+
135+
void phase2a_determine_worklists();
136+
bool phase2b_forward_oops();
137+
void phase2c_prepare_serial_compaction();
138+
131139
void phase3_adjust_pointers();
132140
void phase4_do_compaction();
133141

src/hotspot/share/gc/g1/g1FullCollector.inline.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,10 @@ bool G1FullCollector::is_skip_marking(oop obj) const {
4343
return _region_attr_table.is_skip_marking(cast_from_oop<HeapWord*>(obj));
4444
}
4545

46+
bool G1FullCollector::is_compaction_target(uint region_index) const {
47+
return _region_attr_table.is_compacting(region_index) || is_free(region_index);
48+
}
49+
4650
void G1FullCollector::set_free(uint region_idx) {
4751
_region_attr_table.set_free(region_idx);
4852
}

src/hotspot/share/gc/g1/g1FullGCHeapRegionAttr.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -70,6 +70,10 @@ class G1FullGCHeapRegionAttr : public G1BiasedMappedArray<uint8_t> {
7070
return get_by_address(obj) == Compacting;
7171
}
7272

73+
bool is_compacting(uint idx) const {
74+
return get_by_index(idx) == Compacting;
75+
}
76+
7377
bool is_skip_compacting(uint idx) const {
7478
return get_by_index(idx) == SkipCompacting;
7579
}

0 commit comments

Comments
 (0)