Skip to content

Commit 341de49

Browse files
author
Thomas Schatzl
committed
8273492: Move evacuation failure handling into G1YoungCollector
Reviewed-by: sjohanss, ayang
1 parent 13e9ea9 commit 341de49

13 files changed

+113
-95
lines changed

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

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,8 +1752,6 @@ jint G1CollectedHeap::initialize() {
17521752

17531753
_collection_set.initialize(max_reserved_regions());
17541754

1755-
_evac_failure_regions.initialize(max_reserved_regions());
1756-
17571755
evac_failure_injector()->reset();
17581756

17591757
G1InitLogger::print();
@@ -2772,10 +2770,6 @@ void G1CollectedHeap::verify_after_young_collection(G1HeapVerifier::G1VerifyType
27722770
return;
27732771
}
27742772
Ticks start = Ticks::now();
2775-
// Inject evacuation failure tag into type if needed.
2776-
if (evacuation_failed()) {
2777-
type = (G1HeapVerifier::G1VerifyType)(type | G1HeapVerifier::G1VerifyYoungEvacFail);
2778-
}
27792773
if (VerifyRememberedSets) {
27802774
log_info(gc, verify)("[Verifying RemSets after GC]");
27812775
VerifyRegionRemSetClosure v_cl;
@@ -2884,7 +2878,7 @@ void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_paus
28842878
bool should_start_concurrent_mark_operation = collector_state()->in_concurrent_start_gc();
28852879

28862880
// Perform the collection.
2887-
G1YoungCollector collector(gc_cause(), target_pause_time_ms, &_evac_failure_regions);
2881+
G1YoungCollector collector(gc_cause(), target_pause_time_ms);
28882882
collector.collect();
28892883

28902884
// It should now be safe to tell the concurrent mark thread to start
@@ -3392,8 +3386,8 @@ void G1CollectedHeap::unregister_nmethod(nmethod* nm) {
33923386
nm->oops_do(&reg_cl, true);
33933387
}
33943388

3395-
void G1CollectedHeap::update_used_after_gc() {
3396-
if (evacuation_failed()) {
3389+
void G1CollectedHeap::update_used_after_gc(bool evacuation_failed) {
3390+
if (evacuation_failed) {
33973391
// Reset the G1EvacuationFailureALot counters and flags
33983392
evac_failure_injector()->reset();
33993393

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
#include "gc/g1/g1ConcurrentMark.hpp"
3535
#include "gc/g1/g1EdenRegions.hpp"
3636
#include "gc/g1/g1EvacStats.hpp"
37-
#include "gc/g1/g1EvacFailureRegions.hpp"
3837
#include "gc/g1/g1GCPauseType.hpp"
3938
#include "gc/g1/g1HeapTransition.hpp"
4039
#include "gc/g1/g1HeapVerifier.hpp"
@@ -816,8 +815,6 @@ class G1CollectedHeap : public CollectedHeap {
816815
// The parallel task queues
817816
G1ScannerTasksQueueSet *_task_queues;
818817

819-
G1EvacFailureRegions _evac_failure_regions;
820-
821818
// ("Weak") Reference processing support.
822819
//
823820
// G1 has 2 instances of the reference processor class.
@@ -1035,9 +1032,6 @@ class G1CollectedHeap : public CollectedHeap {
10351032

10361033
void start_concurrent_gc_for_metadata_allocation(GCCause::Cause gc_cause);
10371034

1038-
// True iff an evacuation has failed in the most-recent collection.
1039-
inline bool evacuation_failed() const;
1040-
10411035
void remove_from_old_gen_sets(const uint old_regions_removed,
10421036
const uint archive_regions_removed,
10431037
const uint humongous_regions_removed);
@@ -1283,7 +1277,7 @@ class G1CollectedHeap : public CollectedHeap {
12831277

12841278
// Recalculate amount of used memory after GC. Must be called after all allocation
12851279
// has finished.
1286-
void update_used_after_gc();
1280+
void update_used_after_gc(bool evacuation_failed);
12871281
// Reset and re-enable the hot card cache.
12881282
// Note the counts for the cards in the regions in the
12891283
// collection set are reset when the collection set is freed.

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,6 @@ void G1CollectedHeap::register_optional_region_with_region_attr(HeapRegion* r) {
201201
_region_attr.set_optional(r->hrm_index(), r->rem_set()->is_tracked());
202202
}
203203

204-
bool G1CollectedHeap::evacuation_failed() const {
205-
return _evac_failure_regions.num_regions_failed_evacuation() > 0;
206-
}
207-
208204
inline bool G1CollectedHeap::is_in_young(const oop obj) {
209205
if (obj == NULL) {
210206
return false;

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,35 @@
2525
#include "precompiled.hpp"
2626

2727
#include "gc/g1/g1CollectedHeap.hpp"
28-
#include "gc/g1/g1EvacFailureRegions.hpp"
28+
#include "gc/g1/g1EvacFailureRegions.inline.hpp"
2929
#include "gc/g1/heapRegion.hpp"
3030
#include "memory/allocation.hpp"
3131
#include "runtime/atomic.hpp"
3232

33-
3433
G1EvacFailureRegions::G1EvacFailureRegions() :
35-
_regions_failed_evacuation(mtGC) {
36-
}
34+
_regions_failed_evacuation(mtGC),
35+
_evac_failure_regions(nullptr),
36+
_evac_failure_regions_cur_length(0),
37+
_max_regions(0) { }
3738

3839
G1EvacFailureRegions::~G1EvacFailureRegions() {
39-
FREE_C_HEAP_ARRAY(uint, _evac_failure_regions);
40+
assert(_evac_failure_regions == nullptr, "not cleaned up");
4041
}
4142

42-
void G1EvacFailureRegions::initialize(uint max_regions) {
43+
void G1EvacFailureRegions::pre_collection(uint max_regions) {
4344
Atomic::store(&_evac_failure_regions_cur_length, 0u);
4445
_max_regions = max_regions;
4546
_regions_failed_evacuation.resize(_max_regions);
4647
_evac_failure_regions = NEW_C_HEAP_ARRAY(uint, _max_regions, mtGC);
4748
}
4849

50+
void G1EvacFailureRegions::post_collection() {
51+
_regions_failed_evacuation.resize(0);
52+
FREE_C_HEAP_ARRAY(uint, _evac_failure_regions);
53+
_evac_failure_regions = nullptr;
54+
_max_regions = 0; // To have any record() attempt fail in the future.
55+
}
56+
4957
void G1EvacFailureRegions::par_iterate(HeapRegionClosure* closure,
5058
HeapRegionClaimer* _hrclaimer,
5159
uint worker_id) {
@@ -56,11 +64,6 @@ void G1EvacFailureRegions::par_iterate(HeapRegionClosure* closure,
5664
worker_id);
5765
}
5866

59-
void G1EvacFailureRegions::reset() {
60-
Atomic::store(&_evac_failure_regions_cur_length, 0u);
61-
_regions_failed_evacuation.clear();
62-
}
63-
6467
bool G1EvacFailureRegions::contains(uint region_idx) const {
6568
assert(region_idx < _max_regions, "must be");
6669
return _regions_failed_evacuation.par_at(region_idx, memory_order_relaxed);

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,11 @@ class G1EvacFailureRegions {
4747
public:
4848
G1EvacFailureRegions();
4949
~G1EvacFailureRegions();
50-
void initialize(uint max_regions);
5150

52-
void reset();
51+
// Sets up the bitmap and failed regions array for addition.
52+
void pre_collection(uint max_regions);
53+
// Drops memory for internal data structures, but keep counts.
54+
void post_collection();
5355

5456
bool contains(uint region_idx) const;
5557
void par_iterate(HeapRegionClosure* closure,
@@ -60,6 +62,10 @@ class G1EvacFailureRegions {
6062
return Atomic::load(&_evac_failure_regions_cur_length);
6163
}
6264

65+
bool evacuation_failed() const {
66+
return num_regions_failed_evacuation() > 0;
67+
}
68+
6369
// Record that the garbage collection encountered an evacuation failure in the
6470
// given region. Returns whether this has been the first occurrence of an evacuation
6571
// failure in that region.

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ double G1GCPhaseTimes::print_evacuate_initial_collection_set() const {
457457
return _cur_collection_initial_evac_time_ms + _cur_merge_heap_roots_time_ms;
458458
}
459459

460-
double G1GCPhaseTimes::print_post_evacuate_collection_set() const {
460+
double G1GCPhaseTimes::print_post_evacuate_collection_set(bool evacuation_failed) const {
461461
const double sum_ms = _cur_collection_nmethod_list_cleanup_time_ms +
462462
_recorded_preserve_cm_referents_time_ms +
463463
_cur_ref_proc_time_ms +
@@ -481,13 +481,13 @@ double G1GCPhaseTimes::print_post_evacuate_collection_set() const {
481481
debug_phase(_gc_par_phases[MergePSS], 1);
482482
debug_phase(_gc_par_phases[ClearCardTable], 1);
483483
debug_phase(_gc_par_phases[RecalculateUsed], 1);
484-
if (G1CollectedHeap::heap()->evacuation_failed()) {
484+
if (evacuation_failed) {
485485
debug_phase(_gc_par_phases[RemoveSelfForwardingPtr], 1);
486486
}
487487

488488
trace_phase(_gc_par_phases[RedirtyCards]);
489489
debug_time("Post Evacuate Cleanup 2", _cur_post_evacuate_cleanup_2_time_ms);
490-
if (G1CollectedHeap::heap()->evacuation_failed()) {
490+
if (evacuation_failed) {
491491
debug_phase(_gc_par_phases[RecalculateUsed], 1);
492492
debug_phase(_gc_par_phases[RestorePreservedMarks], 1);
493493
}
@@ -526,7 +526,7 @@ void G1GCPhaseTimes::print_other(double accounted_ms) const {
526526
info_time("Other", _gc_pause_time_ms - accounted_ms);
527527
}
528528

529-
void G1GCPhaseTimes::print() {
529+
void G1GCPhaseTimes::print(bool evacuation_failed) {
530530
// Check if some time has been recorded for verification and only then print
531531
// the message. We do not use Verify*GC here to print because VerifyGCType
532532
// further limits actual verification.
@@ -538,7 +538,7 @@ void G1GCPhaseTimes::print() {
538538
accounted_ms += print_pre_evacuate_collection_set();
539539
accounted_ms += print_evacuate_initial_collection_set();
540540
accounted_ms += print_evacuate_optional_collection_set();
541-
accounted_ms += print_post_evacuate_collection_set();
541+
accounted_ms += print_post_evacuate_collection_set(evacuation_failed);
542542
print_other(accounted_ms);
543543

544544
// See above comment on the _cur_verify_before_time_ms check.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,14 +227,14 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
227227
double print_merge_heap_roots_time() const;
228228
double print_evacuate_initial_collection_set() const;
229229
double print_evacuate_optional_collection_set() const;
230-
double print_post_evacuate_collection_set() const;
230+
double print_post_evacuate_collection_set(bool evacuation_failed) const;
231231
void print_other(double accounted_ms) const;
232232

233233
public:
234234
G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads);
235235
void record_gc_pause_start();
236236
void record_gc_pause_end();
237-
void print();
237+
void print(bool evacuation_failed);
238238
static const char* phase_name(GCParPhases phase);
239239

240240
// record the time a phase took in seconds

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "utilities/ticks.hpp"
3939

4040
class G1CardTable;
41+
class G1EvacFailureRegions;
4142
class G1EvacuationRootClosures;
4243
class G1OopStarChunkedList;
4344
class G1PLABAllocator;

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

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ double G1Policy::logged_cards_processing_time() const {
629629
// Anything below that is considered to be zero
630630
#define MIN_TIMER_GRANULARITY 0.0000001
631631

632-
void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mark) {
632+
void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mark, bool evacuation_failure) {
633633
G1GCPhaseTimes* p = phase_times();
634634

635635
double start_time_sec = phase_times()->cur_collection_start_sec();
@@ -638,8 +638,6 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
638638

639639
G1GCPauseType this_pause = collector_state()->young_gc_pause_type(concurrent_operation_is_full_mark);
640640

641-
bool update_stats = should_update_gc_stats();
642-
643641
if (G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause)) {
644642
record_concurrent_mark_init_end();
645643
} else {
@@ -654,6 +652,10 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
654652
app_time_ms = 1.0;
655653
}
656654

655+
// Evacuation failures skew the timing too much to be considered for some statistics updates.
656+
// We make the assumption that these are rare.
657+
bool update_stats = !evacuation_failure;
658+
657659
if (update_stats) {
658660
// We maintain the invariant that all objects allocated by mutator
659661
// threads will be allocated out of eden regions. So, we can use
@@ -668,7 +670,7 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar
668670
_analytics->report_alloc_rate_ms(alloc_rate_ms);
669671
}
670672

671-
record_pause(this_pause, start_time_sec, end_time_sec);
673+
record_pause(this_pause, start_time_sec, end_time_sec, evacuation_failure);
672674

673675
if (G1GCPauseTypeHelper::is_last_young_pause(this_pause)) {
674676
assert(!G1GCPauseTypeHelper::is_concurrent_start_pause(this_pause),
@@ -891,9 +893,9 @@ void G1Policy::report_ihop_statistics() {
891893
_ihop_control->print();
892894
}
893895

894-
void G1Policy::record_young_gc_pause_end() {
896+
void G1Policy::record_young_gc_pause_end(bool evacuation_failed) {
895897
phase_times()->record_gc_pause_end();
896-
phase_times()->print();
898+
phase_times()->print(evacuation_failed);
897899
}
898900

899901
double G1Policy::predict_base_elapsed_time_ms(size_t pending_cards,
@@ -1176,12 +1178,6 @@ void G1Policy::maybe_start_marking() {
11761178
}
11771179
}
11781180

1179-
bool G1Policy::should_update_gc_stats() {
1180-
// Evacuation failures skew the timing too much to be considered for statistics updates.
1181-
// We make the assumption that these are rare.
1182-
return !_g1h->evacuation_failed();
1183-
}
1184-
11851181
void G1Policy::update_gc_pause_time_ratios(G1GCPauseType gc_type, double start_time_sec, double end_time_sec) {
11861182

11871183
double pause_time_sec = end_time_sec - start_time_sec;
@@ -1199,13 +1195,14 @@ void G1Policy::update_gc_pause_time_ratios(G1GCPauseType gc_type, double start_t
11991195

12001196
void G1Policy::record_pause(G1GCPauseType gc_type,
12011197
double start,
1202-
double end) {
1198+
double end,
1199+
bool evacuation_failure) {
12031200
// Manage the MMU tracker. For some reason it ignores Full GCs.
12041201
if (gc_type != G1GCPauseType::FullGC) {
12051202
_mmu_tracker->add_pause(start, end);
12061203
}
12071204

1208-
if (should_update_gc_stats()) {
1205+
if (!evacuation_failure) {
12091206
update_gc_pause_time_ratios(gc_type, start, end);
12101207
}
12111208

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,10 @@ class G1Policy: public CHeapObj<mtGC> {
269269
// Manage time-to-mixed tracking.
270270
void update_time_to_mixed_tracking(G1GCPauseType gc_type, double start, double end);
271271
// Record the given STW pause with the given start and end times (in s).
272-
void record_pause(G1GCPauseType gc_type, double start, double end);
273-
274-
bool should_update_gc_stats();
272+
void record_pause(G1GCPauseType gc_type,
273+
double start,
274+
double end,
275+
bool evacuation_failure = false);
275276

276277
void update_gc_pause_time_ratios(G1GCPauseType gc_type, double start_sec, double end_sec);
277278

@@ -303,7 +304,7 @@ class G1Policy: public CHeapObj<mtGC> {
303304

304305
// Record the start and end of the young gc pause.
305306
void record_young_gc_pause_start();
306-
void record_young_gc_pause_end();
307+
void record_young_gc_pause_end(bool evacuation_failed);
307308

308309
bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0);
309310

@@ -313,7 +314,7 @@ class G1Policy: public CHeapObj<mtGC> {
313314

314315
// Record the start and end of the actual collection part of the evacuation pause.
315316
void record_young_collection_start();
316-
void record_young_collection_end(bool concurrent_operation_is_full_mark);
317+
void record_young_collection_end(bool concurrent_operation_is_full_mark, bool evacuation_failure);
317318

318319
// Record the start and end of a full collection.
319320
void record_full_collection_start();

0 commit comments

Comments
 (0)