2525 */
2626
2727#include " precompiled.hpp"
28- #include " memory/allocation.hpp"
29- #include " memory/universe.hpp"
28+
29+ #include " cds/archiveHeapWriter.hpp"
30+ #include " classfile/systemDictionary.hpp"
31+ #include " code/codeCache.hpp"
3032
3133#include " gc/shared/classUnloadingContext.hpp"
3234#include " gc/shared/fullGCForwarding.hpp"
4244#include " gc/shenandoah/heuristics/shenandoahYoungHeuristics.hpp"
4345#include " gc/shenandoah/shenandoahAllocRequest.hpp"
4446#include " gc/shenandoah/shenandoahBarrierSet.hpp"
45- #include " gc/shenandoah/shenandoahClosures.inline .hpp"
47+ #include " gc/shenandoah/shenandoahCodeRoots .hpp"
4648#include " gc/shenandoah/shenandoahCollectionSet.hpp"
4749#include " gc/shenandoah/shenandoahCollectorPolicy.hpp"
4850#include " gc/shenandoah/shenandoahConcurrentMark.hpp"
49- #include " gc/shenandoah/shenandoahMarkingContext.inline.hpp"
5051#include " gc/shenandoah/shenandoahControlThread.hpp"
52+ #include " gc/shenandoah/shenandoahClosures.inline.hpp"
5153#include " gc/shenandoah/shenandoahFreeSet.hpp"
5254#include " gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp"
5355#include " gc/shenandoah/shenandoahGenerationalHeap.hpp"
5456#include " gc/shenandoah/shenandoahGlobalGeneration.hpp"
55- #include " gc/shenandoah/shenandoahPhaseTimings.hpp"
5657#include " gc/shenandoah/shenandoahHeap.inline.hpp"
5758#include " gc/shenandoah/shenandoahHeapRegionClosures.hpp"
5859#include " gc/shenandoah/shenandoahHeapRegion.inline.hpp"
6566#include " gc/shenandoah/shenandoahPacer.inline.hpp"
6667#include " gc/shenandoah/shenandoahPadding.hpp"
6768#include " gc/shenandoah/shenandoahParallelCleaning.inline.hpp"
69+ #include " gc/shenandoah/shenandoahPhaseTimings.hpp"
6870#include " gc/shenandoah/shenandoahReferenceProcessor.hpp"
6971#include " gc/shenandoah/shenandoahRootProcessor.inline.hpp"
7072#include " gc/shenandoah/shenandoahScanRemembered.inline.hpp"
7173#include " gc/shenandoah/shenandoahSTWMark.hpp"
74+ #include " gc/shenandoah/shenandoahUncommitThread.hpp"
7275#include " gc/shenandoah/shenandoahUtils.hpp"
7376#include " gc/shenandoah/shenandoahVerifier.hpp"
74- #include " gc/shenandoah/shenandoahCodeRoots.hpp"
7577#include " gc/shenandoah/shenandoahVMOperations.hpp"
7678#include " gc/shenandoah/shenandoahWorkGroup.hpp"
7779#include " gc/shenandoah/shenandoahWorkerPolicy.hpp"
7880#include " gc/shenandoah/shenandoahYoungGeneration.hpp"
7981#include " gc/shenandoah/mode/shenandoahGenerationalMode.hpp"
8082#include " gc/shenandoah/mode/shenandoahPassiveMode.hpp"
8183#include " gc/shenandoah/mode/shenandoahSATBMode.hpp"
82- #include " utilities/globalDefinitions.hpp"
8384
8485#if INCLUDE_JFR
8586#include " gc/shenandoah/shenandoahJfrSupport.hpp"
8687#endif
8788
88- #include " cds/archiveHeapWriter.hpp"
89- #include " classfile/systemDictionary.hpp"
90- #include " code/codeCache.hpp"
89+
90+ #include " memory/allocation.hpp"
9191#include " memory/classLoaderMetaspace.hpp"
9292#include " memory/metaspaceUtils.hpp"
93+ #include " memory/universe.hpp"
9394#include " nmt/mallocTracker.hpp"
9495#include " nmt/memTracker.hpp"
9596#include " oops/compressedOops.inline.hpp"
102103#include " runtime/safepointMechanism.hpp"
103104#include " runtime/stackWatermarkSet.hpp"
104105#include " runtime/vmThread.hpp"
106+ #include " utilities/globalDefinitions.hpp"
105107#include " utilities/events.hpp"
106108#include " utilities/powerOfTwo.hpp"
107109
@@ -459,6 +461,10 @@ jint ShenandoahHeap::initialize() {
459461
460462 initialize_controller ();
461463
464+ if (ShenandoahUncommit) {
465+ _uncommit_thread = new ShenandoahUncommitThread (this );
466+ }
467+
462468 print_init_logger ();
463469
464470 FullGCForwarding::initialize (_heap_region);
@@ -530,6 +536,7 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
530536 _update_refs_iterator(this ),
531537 _global_generation(nullptr ),
532538 _control_thread(nullptr ),
539+ _uncommit_thread(nullptr ),
533540 _young_generation(nullptr ),
534541 _old_generation(nullptr ),
535542 _shenandoah_policy(policy),
@@ -800,60 +807,15 @@ bool ShenandoahHeap::is_in(const void* p) const {
800807 }
801808}
802809
803- void ShenandoahHeap::maybe_uncommit (double shrink_before, size_t shrink_until) {
804- assert (ShenandoahUncommit, " should be enabled" );
805-
806- // Determine if there is work to do. This avoids taking heap lock if there is
807- // no work available, avoids spamming logs with superfluous logging messages,
808- // and minimises the amount of work while locks are taken.
809-
810- if (committed () <= shrink_until) return ;
811-
812- bool has_work = false ;
813- for (size_t i = 0 ; i < num_regions (); i++) {
814- ShenandoahHeapRegion* r = get_region (i);
815- if (r->is_empty_committed () && (r->empty_time () < shrink_before)) {
816- has_work = true ;
817- break ;
818- }
819- }
820-
821- if (has_work) {
822- static const char * msg = " Concurrent uncommit" ;
823- ShenandoahConcurrentPhase gcPhase (msg, ShenandoahPhaseTimings::conc_uncommit, true /* log_heap_usage */ );
824- EventMark em (" %s" , msg);
825-
826- op_uncommit (shrink_before, shrink_until);
810+ void ShenandoahHeap::notify_soft_max_changed () {
811+ if (_uncommit_thread != nullptr ) {
812+ _uncommit_thread->notify_soft_max_changed ();
827813 }
828814}
829815
830- void ShenandoahHeap::op_uncommit (double shrink_before, size_t shrink_until) {
831- assert (ShenandoahUncommit, " should be enabled" );
832-
833- // Application allocates from the beginning of the heap, and GC allocates at
834- // the end of it. It is more efficient to uncommit from the end, so that applications
835- // could enjoy the near committed regions. GC allocations are much less frequent,
836- // and therefore can accept the committing costs.
837-
838- size_t count = 0 ;
839- for (size_t i = num_regions (); i > 0 ; i--) { // care about size_t underflow
840- ShenandoahHeapRegion* r = get_region (i - 1 );
841- if (r->is_empty_committed () && (r->empty_time () < shrink_before)) {
842- ShenandoahHeapLocker locker (lock ());
843- if (r->is_empty_committed ()) {
844- if (committed () < shrink_until + ShenandoahHeapRegion::region_size_bytes ()) {
845- break ;
846- }
847-
848- r->make_uncommitted ();
849- count++;
850- }
851- }
852- SpinPause (); // allow allocators to take the lock
853- }
854-
855- if (count > 0 ) {
856- notify_heap_changed ();
816+ void ShenandoahHeap::notify_explicit_gc_requested () {
817+ if (_uncommit_thread != nullptr ) {
818+ _uncommit_thread->notify_explicit_gc_requested ();
857819 }
858820}
859821
@@ -1507,6 +1469,10 @@ void ShenandoahHeap::gc_threads_do(ThreadClosure* tcl) const {
15071469 tcl->do_thread (_control_thread);
15081470 }
15091471
1472+ if (_uncommit_thread != nullptr ) {
1473+ tcl->do_thread (_uncommit_thread);
1474+ }
1475+
15101476 workers ()->threads_do (tcl);
15111477 if (_safepoint_workers != nullptr ) {
15121478 _safepoint_workers->threads_do (tcl);
@@ -2094,6 +2060,11 @@ void ShenandoahHeap::stop() {
20942060
20952061 // Step 3. Wait until GC worker exits normally.
20962062 control_thread ()->stop ();
2063+
2064+ // Stop 4. Shutdown uncommit thread.
2065+ if (_uncommit_thread != nullptr ) {
2066+ _uncommit_thread->stop ();
2067+ }
20972068}
20982069
20992070void ShenandoahHeap::stw_unload_classes (bool full_gc) {
@@ -2521,7 +2492,7 @@ bool ShenandoahHeap::uncommit_bitmap_slice(ShenandoahHeapRegion *r) {
25212492
25222493 if (is_bitmap_slice_committed (r, true )) {
25232494 // Some other region from the group is still committed, meaning the bitmap
2524- // slice is should stay committed, exit right away.
2495+ // slice should stay committed, exit right away.
25252496 return true ;
25262497 }
25272498
@@ -2535,6 +2506,27 @@ bool ShenandoahHeap::uncommit_bitmap_slice(ShenandoahHeapRegion *r) {
25352506 return true ;
25362507}
25372508
2509+ void ShenandoahHeap::forbid_uncommit () {
2510+ if (_uncommit_thread != nullptr ) {
2511+ _uncommit_thread->forbid_uncommit ();
2512+ }
2513+ }
2514+
2515+ void ShenandoahHeap::allow_uncommit () {
2516+ if (_uncommit_thread != nullptr ) {
2517+ _uncommit_thread->allow_uncommit ();
2518+ }
2519+ }
2520+
2521+ #ifdef ASSERT
2522+ bool ShenandoahHeap::is_uncommit_in_progress () {
2523+ if (_uncommit_thread != nullptr ) {
2524+ return _uncommit_thread->is_uncommit_in_progress ();
2525+ }
2526+ return false ;
2527+ }
2528+ #endif
2529+
25382530void ShenandoahHeap::safepoint_synchronize_begin () {
25392531 StackWatermarkSet::safepoint_synchronize_begin ();
25402532 SuspendibleThreadSet::synchronize ();
0 commit comments