8302215: G1: Last-ditch Full GC should do serial compaction for tail regions in per thread compaction points.
Reviewed-by: ayang, sjohanss, tschatzl
This commit is contained in:
parent
7e08275cc1
commit
eaae0baeba
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, 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
|
||||
@ -327,7 +327,7 @@ void G1FullCollector::phase2_prepare_compaction() {
|
||||
// Try to avoid OOM immediately after Full GC in case there are no free regions
|
||||
// left after determining the result locations (i.e. this phase). Prepare to
|
||||
// maximally compact the tail regions of the compaction queues serially.
|
||||
if (!has_free_compaction_targets) {
|
||||
if (scope()->do_maximal_compaction() || !has_free_compaction_targets) {
|
||||
phase2c_prepare_serial_compaction();
|
||||
}
|
||||
}
|
||||
@ -348,37 +348,67 @@ bool G1FullCollector::phase2b_forward_oops() {
|
||||
return task.has_free_compaction_targets();
|
||||
}
|
||||
|
||||
void G1FullCollector::phase2c_prepare_serial_compaction() {
|
||||
GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare serial compaction", scope()->timer());
|
||||
// At this point we know that after parallel compaction there will be no
|
||||
// completely free regions. That means that the last region of
|
||||
// all compaction queues still have data in them. We try to compact
|
||||
// these regions in serial to avoid a premature OOM when the mutator wants
|
||||
// to allocate the first eden region after gc.
|
||||
uint G1FullCollector::truncate_parallel_cps() {
|
||||
uint lowest_current = (uint)-1;
|
||||
for (uint i = 0; i < workers(); i++) {
|
||||
G1FullGCCompactionPoint* cp = compaction_point(i);
|
||||
if (cp->has_regions()) {
|
||||
serial_compaction_point()->add(cp->remove_last());
|
||||
lowest_current = MIN2(lowest_current, cp->current_region()->hrm_index());
|
||||
}
|
||||
}
|
||||
|
||||
// Update the forwarding information for the regions in the serial
|
||||
// compaction point.
|
||||
G1FullGCCompactionPoint* cp = serial_compaction_point();
|
||||
for (GrowableArrayIterator<HeapRegion*> it = cp->regions()->begin(); it != cp->regions()->end(); ++it) {
|
||||
HeapRegion* current = *it;
|
||||
if (!cp->is_initialized()) {
|
||||
// Initialize the compaction point. Nothing more is needed for the first heap region
|
||||
// since it is already prepared for compaction.
|
||||
cp->initialize(current);
|
||||
} else {
|
||||
assert(!current->is_humongous(), "Should be no humongous regions in compaction queue");
|
||||
G1SerialRePrepareClosure re_prepare(cp, current);
|
||||
if (lowest_current == (uint)-1) {
|
||||
// worker compaction points are empty
|
||||
return lowest_current;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < workers(); i++) {
|
||||
G1FullGCCompactionPoint* cp = compaction_point(i);
|
||||
if (cp->has_regions()) {
|
||||
cp->remove_at_or_above(lowest_current);
|
||||
}
|
||||
}
|
||||
return lowest_current;
|
||||
}
|
||||
|
||||
void G1FullCollector::phase2c_prepare_serial_compaction() {
|
||||
GCTraceTime(Debug, gc, phases) debug("Phase 2: Prepare serial compaction", scope()->timer());
|
||||
// At this point, we know that after parallel compaction there will be regions that
|
||||
// are partially compacted into. Thus, the last compaction region of all
|
||||
// compaction queues still have space in them. We try to re-compact these regions
|
||||
// in serial to avoid a premature OOM when the mutator wants to allocate the first
|
||||
// eden region after gc.
|
||||
|
||||
// For maximum compaction, we need to re-prepare all objects above the lowest
|
||||
// region among the current regions for all thread compaction points. It may
|
||||
// happen that due to the uneven distribution of objects to parallel threads, holes
|
||||
// have been created as threads compact to different target regions between the
|
||||
// lowest and the highest region in the tails of the compaction points.
|
||||
|
||||
uint start_serial = truncate_parallel_cps();
|
||||
if (start_serial >= _heap->max_reserved_regions()) {
|
||||
return;
|
||||
}
|
||||
|
||||
G1FullGCCompactionPoint* serial_cp = serial_compaction_point();
|
||||
assert(!serial_cp->is_initialized(), "sanity!");
|
||||
|
||||
HeapRegion* start_hr = _heap->region_at(start_serial);
|
||||
serial_cp->add(start_hr);
|
||||
serial_cp->initialize(start_hr);
|
||||
|
||||
HeapWord* dense_prefix_top = compaction_top(start_hr);
|
||||
G1SerialRePrepareClosure re_prepare(serial_cp, dense_prefix_top);
|
||||
|
||||
for (uint i = start_serial + 1; i < _heap->max_reserved_regions(); i++) {
|
||||
if (is_compaction_target(i)) {
|
||||
HeapRegion* current = _heap->region_at(i);
|
||||
set_compaction_top(current, current->bottom());
|
||||
serial_cp->add(current);
|
||||
current->apply_to_marked_objects(mark_bitmap(), &re_prepare);
|
||||
}
|
||||
}
|
||||
cp->update();
|
||||
serial_cp->update();
|
||||
}
|
||||
|
||||
void G1FullCollector::phase3_adjust_pointers() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, 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
|
||||
@ -137,6 +137,8 @@ public:
|
||||
inline void set_compaction_top(HeapRegion* r, HeapWord* value);
|
||||
inline HeapWord* compaction_top(HeapRegion* r) const;
|
||||
|
||||
uint truncate_parallel_cps();
|
||||
|
||||
private:
|
||||
void phase1_mark_live_objects();
|
||||
void phase2_prepare_compaction();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, 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
|
||||
@ -116,6 +116,17 @@ void G1FullGCCompactionPoint::add(HeapRegion* hr) {
|
||||
_compaction_regions->append(hr);
|
||||
}
|
||||
|
||||
HeapRegion* G1FullGCCompactionPoint::remove_last() {
|
||||
return _compaction_regions->pop();
|
||||
void G1FullGCCompactionPoint::remove_at_or_above(uint bottom) {
|
||||
HeapRegion* cur = current_region();
|
||||
assert(cur->hrm_index() >= bottom, "Sanity!");
|
||||
|
||||
int start_index = 0;
|
||||
for (HeapRegion* r : *_compaction_regions) {
|
||||
if (r->hrm_index() < bottom) {
|
||||
start_index++;
|
||||
}
|
||||
}
|
||||
|
||||
assert(start_index >= 0, "Should have at least one region");
|
||||
_compaction_regions->trunc_to(start_index);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, 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
|
||||
@ -55,7 +55,7 @@ public:
|
||||
void forward(oop object, size_t size);
|
||||
void add(HeapRegion* hr);
|
||||
|
||||
HeapRegion* remove_last();
|
||||
void remove_at_or_above(uint bottom);
|
||||
HeapRegion* current_region();
|
||||
|
||||
GrowableArray<HeapRegion*>* regions();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, 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
|
||||
@ -119,12 +119,12 @@ private:
|
||||
// serial compaction.
|
||||
class G1SerialRePrepareClosure : public StackObj {
|
||||
G1FullGCCompactionPoint* _cp;
|
||||
HeapRegion* _current;
|
||||
HeapWord* _dense_prefix_top;
|
||||
|
||||
public:
|
||||
G1SerialRePrepareClosure(G1FullGCCompactionPoint* hrcp, HeapRegion* hr) :
|
||||
G1SerialRePrepareClosure(G1FullGCCompactionPoint* hrcp, HeapWord* dense_prefix_top) :
|
||||
_cp(hrcp),
|
||||
_current(hr) { }
|
||||
_dense_prefix_top(dense_prefix_top) { }
|
||||
|
||||
inline size_t apply(oop obj);
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2023, 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
|
||||
@ -110,10 +110,12 @@ inline bool G1DetermineCompactionQueueClosure::do_heap_region(HeapRegion* hr) {
|
||||
}
|
||||
|
||||
inline size_t G1SerialRePrepareClosure::apply(oop obj) {
|
||||
// We only re-prepare objects forwarded within the current region, so
|
||||
// skip objects that are already forwarded to another region.
|
||||
if (obj->is_forwarded() && !_current->is_in(obj->forwardee())) {
|
||||
return obj->size();
|
||||
if (obj->is_forwarded()) {
|
||||
// We skip objects compiled into the first region or
|
||||
// into regions not part of the serial compaction point.
|
||||
if (cast_from_oop<HeapWord*>(obj->forwardee()) < _dense_prefix_top) {
|
||||
return obj->size();
|
||||
}
|
||||
}
|
||||
|
||||
// Get size and forward.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, 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
|
||||
@ -43,6 +43,7 @@ G1FullGCScope::G1FullGCScope(G1MonitoringSupport* monitoring_support,
|
||||
G1FullGCTracer* tracer) :
|
||||
_rm(),
|
||||
_explicit_gc(explicit_gc),
|
||||
_do_maximal_compaction(do_maximal_compaction),
|
||||
_g1h(G1CollectedHeap::heap()),
|
||||
_svc_marker(SvcGCMarker::FULL),
|
||||
_timer(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2023, 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
|
||||
@ -48,6 +48,7 @@ public:
|
||||
class G1FullGCScope : public StackObj {
|
||||
ResourceMark _rm;
|
||||
bool _explicit_gc;
|
||||
bool _do_maximal_compaction;
|
||||
G1CollectedHeap* _g1h;
|
||||
SvcGCMarker _svc_marker;
|
||||
STWGCTimer _timer;
|
||||
@ -68,6 +69,7 @@ public:
|
||||
|
||||
bool is_explicit_gc();
|
||||
bool should_clear_soft_refs();
|
||||
bool do_maximal_compaction() { return _do_maximal_compaction; }
|
||||
|
||||
STWGCTimer* timer();
|
||||
G1FullGCTracer* tracer();
|
||||
|
Loading…
Reference in New Issue
Block a user