diff --git a/src/hotspot/share/gc/z/zDriver.cpp b/src/hotspot/share/gc/z/zDriver.cpp index 3836f330142..107be979c25 100644 --- a/src/hotspot/share/gc/z/zDriver.cpp +++ b/src/hotspot/share/gc/z/zDriver.cpp @@ -230,8 +230,8 @@ void ZDriverMinor::terminate() { _port.send_async(request); } -static bool should_clear_soft_references(GCCause::Cause cause) { - // Clear soft references if implied by the GC cause +static bool should_clear_all_soft_references(GCCause::Cause cause) { + // Clear all soft references if implied by the GC cause switch (cause) { case GCCause::_wb_full_gc: case GCCause::_metadata_GC_clear_soft_refs: @@ -259,12 +259,12 @@ static bool should_clear_soft_references(GCCause::Cause cause) { break; } - // Clear soft references if threads are stalled waiting for an old collection + // Clear all soft references if threads are stalled waiting for an old collection if (ZHeap::heap()->is_alloc_stalling_for_old()) { return true; } - // Don't clear + // Don't clear all soft references return false; } @@ -302,13 +302,17 @@ static bool should_preclean_young(GCCause::Cause cause) { return true; } - // It is important that when soft references are cleared, we also pre-clean the young - // generation, as we might otherwise throw premature OOM. Therefore, all causes that - // trigger soft ref cleaning must also trigger pre-cleaning of young gen. If allocations - // stalled when checking for soft ref cleaning, then since we hold the driver locker all - // the way until we check for young gen pre-cleaning, we can be certain that we should + // We clear all soft references as a last-ditch effort to collect memory + // before throwing an OOM. Therefore it is important that when the GC policy + // is to clear all soft references, that we also pre-clean the young + // generation, as we might otherwise throw premature OOM. + // + // Therefore, all causes that trigger all soft ref clearing must also trigger + // pre-cleaning of young gen. If allocations stalled when checking for all + // soft ref clearing, then since we hold the driver locker all the way until + // we check for young gen pre-cleaning, we can be certain that we should // catch that above and perform young gen pre-cleaning. - assert(!should_clear_soft_references(cause), "Clearing soft references without pre-cleaning young gen"); + assert(!should_clear_all_soft_references(cause), "Clearing all soft references without pre-cleaning young gen"); return false; } @@ -395,6 +399,10 @@ public: // Select number of worker threads to use ZGeneration::young()->set_active_workers(request.young_nworkers()); ZGeneration::old()->set_active_workers(request.old_nworkers()); + + // Set up soft reference policy + const bool clear_all = should_clear_all_soft_references(request.cause()); + ZGeneration::old()->set_soft_reference_policy(clear_all); } ~ZDriverScopeMajor() { @@ -444,12 +452,13 @@ void ZDriverMajor::gc(const ZDriverRequest& request) { collect_old(); } -static void handle_alloc_stalling_for_old(bool cleared_soft_refs) { - ZHeap::heap()->handle_alloc_stalling_for_old(cleared_soft_refs); +static void handle_alloc_stalling_for_old() { + const bool cleared_all = ZGeneration::old()->uses_clear_all_soft_reference_policy(); + ZHeap::heap()->handle_alloc_stalling_for_old(cleared_all); } -void ZDriverMajor::handle_alloc_stalls(bool cleared_soft_refs) const { - handle_alloc_stalling_for_old(cleared_soft_refs); +void ZDriverMajor::handle_alloc_stalls() const { + handle_alloc_stalling_for_old(); } void ZDriverMajor::run_thread() { @@ -464,10 +473,6 @@ void ZDriverMajor::run_thread() { abortpoint(); - // Set up soft reference policy - const bool clear_soft_refs = should_clear_soft_references(request.cause()); - ZGeneration::old()->set_soft_reference_policy(clear_soft_refs); - // Run GC gc(request); @@ -477,7 +482,7 @@ void ZDriverMajor::run_thread() { _port.ack(); // Handle allocation stalls - handle_alloc_stalls(clear_soft_refs); + handle_alloc_stalls(); ZBreakpoint::at_after_gc(); } diff --git a/src/hotspot/share/gc/z/zDriver.hpp b/src/hotspot/share/gc/z/zDriver.hpp index 6291a8f359c..5f1fe08a0b6 100644 --- a/src/hotspot/share/gc/z/zDriver.hpp +++ b/src/hotspot/share/gc/z/zDriver.hpp @@ -112,7 +112,7 @@ private: void collect_old(); void gc(const ZDriverRequest& request); - void handle_alloc_stalls(bool cleared_soft_refs) const; + void handle_alloc_stalls() const; protected: virtual void run_thread(); diff --git a/src/hotspot/share/gc/z/zGeneration.cpp b/src/hotspot/share/gc/z/zGeneration.cpp index 8a7d38e2991..655f47ba49c 100644 --- a/src/hotspot/share/gc/z/zGeneration.cpp +++ b/src/hotspot/share/gc/z/zGeneration.cpp @@ -1286,6 +1286,10 @@ void ZGenerationOld::set_soft_reference_policy(bool clear) { _reference_processor.set_soft_reference_policy(clear); } +bool ZGenerationOld::uses_clear_all_soft_reference_policy() const { + return _reference_processor.uses_clear_all_soft_reference_policy(); +} + class ZRendezvousHandshakeClosure : public HandshakeClosure { public: ZRendezvousHandshakeClosure() diff --git a/src/hotspot/share/gc/z/zGeneration.hpp b/src/hotspot/share/gc/z/zGeneration.hpp index aec48a0a072..3e18919eee4 100644 --- a/src/hotspot/share/gc/z/zGeneration.hpp +++ b/src/hotspot/share/gc/z/zGeneration.hpp @@ -309,6 +309,7 @@ public: // Reference processing ReferenceDiscoverer* reference_discoverer(); void set_soft_reference_policy(bool clear); + bool uses_clear_all_soft_reference_policy() const; uint total_collections_at_start() const; diff --git a/src/hotspot/share/gc/z/zHeap.inline.hpp b/src/hotspot/share/gc/z/zHeap.inline.hpp index d983c002afa..127212aef0b 100644 --- a/src/hotspot/share/gc/z/zHeap.inline.hpp +++ b/src/hotspot/share/gc/z/zHeap.inline.hpp @@ -86,8 +86,8 @@ inline void ZHeap::handle_alloc_stalling_for_young() { _page_allocator.handle_alloc_stalling_for_young(); } -inline void ZHeap::handle_alloc_stalling_for_old(bool cleared_soft_refs) { - _page_allocator.handle_alloc_stalling_for_old(cleared_soft_refs); +inline void ZHeap::handle_alloc_stalling_for_old(bool cleared_all_soft_refs) { + _page_allocator.handle_alloc_stalling_for_old(cleared_all_soft_refs); } inline bool ZHeap::is_oop(uintptr_t addr) const { diff --git a/src/hotspot/share/gc/z/zPageAllocator.cpp b/src/hotspot/share/gc/z/zPageAllocator.cpp index 519c36e556d..b1fb1e48373 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.cpp +++ b/src/hotspot/share/gc/z/zPageAllocator.cpp @@ -985,9 +985,9 @@ void ZPageAllocator::handle_alloc_stalling_for_young() { restart_gc(); } -void ZPageAllocator::handle_alloc_stalling_for_old(bool cleared_soft_refs) { +void ZPageAllocator::handle_alloc_stalling_for_old(bool cleared_all_soft_refs) { ZLocker locker(&_lock); - if (cleared_soft_refs) { + if (cleared_all_soft_refs) { notify_out_of_memory(); } restart_gc(); diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.cpp b/src/hotspot/share/gc/z/zReferenceProcessor.cpp index 1252de2ac27..797bd963536 100644 --- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp +++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp @@ -113,7 +113,7 @@ static void list_append(zaddress& head, zaddress& tail, zaddress reference) { ZReferenceProcessor::ZReferenceProcessor(ZWorkers* workers) : _workers(workers), _soft_reference_policy(nullptr), - _clear_all_soft_refs(false), + _uses_clear_all_soft_reference_policy(false), _encountered_count(), _discovered_count(), _enqueued_count(), @@ -121,13 +121,13 @@ ZReferenceProcessor::ZReferenceProcessor(ZWorkers* workers) _pending_list(zaddress::null), _pending_list_tail(zaddress::null) {} -void ZReferenceProcessor::set_soft_reference_policy(bool clear) { +void ZReferenceProcessor::set_soft_reference_policy(bool clear_all_soft_references) { static AlwaysClearPolicy always_clear_policy; static LRUMaxHeapPolicy lru_max_heap_policy; - _clear_all_soft_refs = clear; + _uses_clear_all_soft_reference_policy = clear_all_soft_references; - if (clear) { + if (clear_all_soft_references) { _soft_reference_policy = &always_clear_policy; } else { _soft_reference_policy = &lru_max_heap_policy; @@ -136,6 +136,10 @@ void ZReferenceProcessor::set_soft_reference_policy(bool clear) { _soft_reference_policy->setup(); } +bool ZReferenceProcessor::uses_clear_all_soft_reference_policy() const { + return _uses_clear_all_soft_reference_policy; +} + bool ZReferenceProcessor::is_inactive(zaddress reference, oop referent, ReferenceType type) const { if (type == REF_FINAL) { // A FinalReference is inactive if its next field is non-null. An application can't @@ -440,7 +444,7 @@ public: void ZReferenceProcessor::process_references() { ZStatTimerOld timer(ZSubPhaseConcurrentReferencesProcess); - if (_clear_all_soft_refs) { + if (_uses_clear_all_soft_reference_policy) { log_info(gc, ref)("Clearing All SoftReferences"); } diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.hpp b/src/hotspot/share/gc/z/zReferenceProcessor.hpp index 7a8900827da..f8e924ed99f 100644 --- a/src/hotspot/share/gc/z/zReferenceProcessor.hpp +++ b/src/hotspot/share/gc/z/zReferenceProcessor.hpp @@ -41,7 +41,7 @@ private: ZWorkers* const _workers; ReferencePolicy* _soft_reference_policy; - bool _clear_all_soft_refs; + bool _uses_clear_all_soft_reference_policy; ZPerWorker _encountered_count; ZPerWorker _discovered_count; ZPerWorker _enqueued_count; @@ -69,7 +69,9 @@ private: public: ZReferenceProcessor(ZWorkers* workers); - void set_soft_reference_policy(bool clear); + void set_soft_reference_policy(bool clear_all_soft_references); + bool uses_clear_all_soft_reference_policy() const; + void reset_statistics(); virtual bool discover_reference(oop reference, ReferenceType type);