diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 845f8a257a1..8d0a640cbd3 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -627,7 +627,8 @@ class G1CollectedHeap : public CollectedHeap { // Remove from the reclaim candidate set. Also remove from the // collection set so that later encounters avoid the slow path. - inline void set_humongous_is_live(oop obj); + template + inline void set_humongous_is_live(T* p, oop obj); // Register the given region to be part of the collection set. inline void register_humongous_candidate_region_with_region_attr(uint index); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp index fdc8585dbc0..8f17a15d523 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp @@ -274,7 +274,8 @@ inline bool G1CollectedHeap::is_humongous_reclaim_candidate(uint region) { return _region_attr.is_humongous_candidate(region); } -inline void G1CollectedHeap::set_humongous_is_live(oop obj) { +template +inline void G1CollectedHeap::set_humongous_is_live(T* p, oop obj) { uint region = addr_to_region(obj); // Reset the entry in the region attribute table so that subsequent // references to the same humongous object do not go into the slow path @@ -283,7 +284,16 @@ inline void G1CollectedHeap::set_humongous_is_live(oop obj) { // humongous-candidate to not, and the write, in evacuation, is // separated from the read, in post-evacuation. if (_region_attr.is_humongous_candidate(region)) { - _region_attr.clear_humongous_candidate(region); + // Avoid that humongous object self-references are keeping the object alive. + // References may be from outside the heap (heap roots), so check this first. + if (!is_in_reserved(p)) { + _region_attr.clear_humongous_candidate(region); + return; + } + G1HeapRegion* from_region = heap_region_containing(p); + if (!from_region->is_humongous() || from_region->humongous_start_region()->hrm_index() != region) { + _region_attr.clear_humongous_candidate(region); + } } } diff --git a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp index 87e3a1cc7c4..943e2d0d703 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp @@ -67,7 +67,7 @@ inline void G1ScanClosureBase::prefetch_and_push(T* p, const oop obj) { template inline void G1ScanClosureBase::handle_non_cset_obj_common(G1HeapRegionAttr const region_attr, T* p, oop const obj) { if (region_attr.is_humongous_candidate()) { - _g1h->set_humongous_is_live(obj); + _g1h->set_humongous_is_live(p, obj); } else if (region_attr.is_optional()) { _par_scan_state->remember_reference_into_optional_region(p); } @@ -255,7 +255,7 @@ void G1ParCopyClosure::do_oop_work(T* p) { } } else { if (state.is_humongous_candidate()) { - _g1h->set_humongous_is_live(obj); + _g1h->set_humongous_is_live(p, obj); } else if ((barrier != G1BarrierNoOptRoots) && state.is_optional()) { _par_scan_state->remember_root_into_optional_region(p); } diff --git a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegions.java b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegions.java index fd1924b9644..962b5a9352a 100644 --- a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegions.java +++ b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegions.java @@ -192,13 +192,17 @@ public static void main(String[] args) throws Exception { class TestEagerReclaimHumongousRegionsClearMarkBitsRunner { private static final WhiteBox WB = WhiteBox.getWhiteBox(); - private static final int SIZE = 1024 * 1024; + private static final int SIZE = 1024 * 1024 * 3 / 2; private static Object allocateHumongousObj(boolean useTypeArray) { if (useTypeArray) { return new int[SIZE]; } else { - return new Object[SIZE]; + Object[] result = new Object[SIZE]; + // Create a self-references from outside the humongous-starts + // region should not prevent reclamation. + result[result.length - 1] = result; + return result; } }