From f6f0d05f65a35672f48f63d7e8f73a8c2f56d1c3 Mon Sep 17 00:00:00 2001
From: mashoubing <mashoubing1@huawei.com>
Date: Wed, 25 Aug 2021 14:22:13 +0800
Subject: [PATCH 4/4] G1Ucommit: Refactor Trigger mechanism

---
 .../g1/concurrentG1RefineThread.cpp           | 65 ---------------
 .../g1/concurrentG1RefineThread.hpp           |  1 -
 .../gc_implementation/g1/concurrentMark.cpp   |  2 +-
 .../gc_implementation/g1/g1CollectedHeap.cpp  | 51 ++++++++----
 .../gc_implementation/g1/g1CollectedHeap.hpp  |  5 +-
 .../g1/g1CollectorPolicy.cpp                  | 60 --------------
 .../g1/g1CollectorPolicy.hpp                  | 20 +----
 .../gc_implementation/g1/g1UncommitThread.cpp | 82 ++++++++++++++++++-
 .../gc_implementation/g1/g1UncommitThread.hpp |  2 +
 .../g1/heapRegionManager.cpp                  | 28 ++++---
 .../g1/heapRegionManager.hpp                  |  2 +-
 .../g1/heapRegionManager.inline.hpp           |  2 +-
 12 files changed, 142 insertions(+), 178 deletions(-)

diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
index 98a43ba62..e4ec84895 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
@@ -100,69 +100,6 @@ void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
   }
 }
 
-bool ConcurrentG1RefineThread::should_start_periodic_gc() {
-  // If we are currently in a concurrent mark we are going to uncommit memory soon.
-  if (G1CollectedHeap::heap()->concurrent_mark()->cmThread()->during_cycle()) {
-    if (G1UncommitLog) {
-      gclog_or_tty->print_cr("Concurrent cycle in progress. Skipping.");
-    }
-    return false;
-  }
-
-  // Check if enough time has passed since the last GC.
-  uintx time_since_last_gc;
-  if ((time_since_last_gc = (uintx)Universe::heap()->millis_since_last_gc()) < G1PeriodicGCInterval) {
-    if (G1UncommitLog) {
-      gclog_or_tty->print_cr("Last GC occurred " UINTX_FORMAT "ms before which is below threshold " UINTX_FORMAT "ms. Skipping.",
-                            time_since_last_gc, G1PeriodicGCInterval);
-    }
-    return false;
-  }
-
-  return true;
-}
-
-void ConcurrentG1RefineThread::check_for_periodic_gc() {
-  if (!G1Uncommit) {
-    return;
-  }
-
-  assert(G1PeriodicGCInterval > 0, "just checking");
-  double recent_load = -1.0;
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  G1CollectorPolicy* g1p = g1h->g1_policy();
-  if (G1PeriodicGCLoadThreshold) {
-    // Sample process load and store it
-    if (G1PeriodicGCProcessLoad) {
-      recent_load = os::get_process_load() * 100;
-    }
-    if (recent_load < 0) {
-      // Fallback to os load
-      G1PeriodicGCProcessLoad = false;
-      if (os::loadavg(&recent_load, 1) != -1) {
-        static int cpu_count = os::active_processor_count();
-        assert(cpu_count > 0, "just checking");
-        recent_load = recent_load * 100 / cpu_count;
-      }
-    }
-    if (recent_load >= 0) {
-      g1p->add_os_load(recent_load);
-    }
-  }
-
-  double now = os::elapsedTime();
-  if (now - _last_periodic_gc_attempt_s > G1PeriodicGCInterval / 1000.0) {
-    if (G1UncommitLog) {
-      recent_load < 0 ? gclog_or_tty->print_cr("Checking for periodic GC.")
-                     : gclog_or_tty->print_cr("Checking for periodic GC. Current load %1.2f. Heap total " UINT32_FORMAT " free " UINT32_FORMAT, recent_load, g1h->_hrm.length(), g1h->_hrm.num_free_regions());
-    }
-    if (should_start_periodic_gc()) {
-      g1p->set_periodic_gc();
-    }
-    _last_periodic_gc_attempt_s = now;
-  }
-}
-
 void ConcurrentG1RefineThread::run_young_rs_sampling() {
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   _vtime_start = os::elapsedVTime();
@@ -175,8 +112,6 @@ void ConcurrentG1RefineThread::run_young_rs_sampling() {
       _vtime_accum = 0.0;
     }
 
-    check_for_periodic_gc();
-
     MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
     if (_should_terminate) {
       break;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp
index 8fa521371..6c712fd2d 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp
@@ -71,7 +71,6 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread {
   void deactivate();
 
   void check_for_periodic_gc();
-  bool should_start_periodic_gc();
 
 public:
   virtual void run();
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
index 447bee183..831ec94fa 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
@@ -1354,7 +1354,7 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) {
     satb_mq_set.set_active_all_threads(false, /* new active value */
                                        true /* expected_active */);
 
-    g1h->extract_uncommit_list();
+    g1h->shrink_heap_at_remark();
     if (VerifyDuringGC) {
       HandleMark hm;  // handle scope
       Universe::heap()->prepare_for_verify();
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index 1f1042caa..6ee33fd05 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -1565,6 +1565,19 @@ void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
 void
 G1CollectedHeap::
 resize_if_necessary_after_full_collection(size_t word_size) {
+  bool should_expand;
+  size_t resize_amount = full_collection_resize_amount(should_expand);
+
+  if (resize_amount == 0) {
+    return;
+  } else if (should_expand) {
+    expand(resize_amount);
+  } else {
+    shrink(resize_amount);
+  }
+}
+
+size_t G1CollectedHeap::full_collection_resize_amount(bool& expand) {
   // Include the current allocation, if any, and bytes that will be
   // pre-allocated to support collections, as "used".
   const size_t capacity_after_gc = capacity();
@@ -1630,8 +1643,8 @@ resize_if_necessary_after_full_collection(size_t word_size) {
                   ergo_format_byte_perc("min desired capacity"),
                   capacity_after_gc, used_after_gc,
                   minimum_desired_capacity, (double) MinHeapFreeRatio);
-    expand(expand_bytes);
-
+    expand = true;
+    return expand_bytes;
     // No expansion, now see if we want to shrink
   } else if (capacity_after_gc > maximum_desired_capacity) {
     // Capacity too large, compute shrinking size
@@ -1645,10 +1658,13 @@ resize_if_necessary_after_full_collection(size_t word_size) {
                   ergo_format_byte_perc("max desired capacity"),
                   capacity_after_gc, used_after_gc,
                   maximum_desired_capacity, (double) MaxHeapFreeRatio);
-    shrink(shrink_bytes);
+    expand = false;
+    return shrink_bytes;
   }
-}
 
+  expand = true;
+  return 0;
+}
 
 HeapWord*
 G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
@@ -2185,12 +2201,6 @@ void G1CollectedHeap::stop() {
   }
 }
 
-void G1CollectedHeap::check_trigger_periodic_gc() {
-  if (g1_policy()->should_trigger_periodic_gc()) {
-    collect(GCCause::_g1_periodic_collection);
-  }
-}
-
 void G1CollectedHeap::init_periodic_gc_thread() {
   if (_uncommit_thread == NULL && G1Uncommit) {
     PeriodicGC::start();
@@ -2198,10 +2208,22 @@ void G1CollectedHeap::init_periodic_gc_thread() {
   }
 }
 
-void G1CollectedHeap::extract_uncommit_list() {
-  if (g1_policy()->can_extract_uncommit_list()) {
-    uint count = _hrm.extract_uncommit_list();
-    g1_policy()->record_extract_uncommit_list(count);
+void G1CollectedHeap::shrink_heap_at_remark() {
+  if (!G1Uncommit) {
+    return;
+  }
+
+  bool should_expand;
+  size_t resize_amount = full_collection_resize_amount(should_expand);
+  uint length = _hrm.length();
+
+  if (resize_amount > 0 && !should_expand) {
+    uint num_candidate_to_remove = (uint)(resize_amount / HeapRegion::GrainBytes);
+    uint count = _hrm.extract_uncommit_list(num_candidate_to_remove);
+
+    gclog_or_tty->print(" [G1Uncommit list " UINT32_FORMAT ", remaining " UINT32_FORMAT
+                        ", free list " UINT32_FORMAT "]",
+                        count, length - count, _hrm.num_free_regions());
   }
 }
 
@@ -4037,7 +4059,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
 
 
     double pause_start_sec = os::elapsedTime();
-    g1_policy()->record_gc_start(pause_start_sec);
     g1_policy()->phase_times()->note_gc_start(active_workers, mark_in_progress());
     log_gc_header();
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
index 3225967b3..d0ec5a773 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
@@ -626,6 +626,8 @@ protected:
   // and will be considered part of the used portion of the heap.
   void resize_if_necessary_after_full_collection(size_t word_size);
 
+  size_t full_collection_resize_amount(bool& expand);
+
   // Callback from VM_G1CollectForAllocation operation.
   // This function does everything necessary/possible to satisfy a
   // failed allocation request (including collection, expansion, etc.)
@@ -1026,9 +1028,8 @@ public:
 
   void set_refine_cte_cl_concurrency(bool concurrent);
 
-  void check_trigger_periodic_gc();
   void init_periodic_gc_thread();
-  void extract_uncommit_list();
+  void shrink_heap_at_remark();
 
   RefToScanQueue *task_queue(int i) const;
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
index 099762f2b..05ce59987 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
@@ -89,7 +89,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
   _concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
 
   _alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
-  _heap_size_seq(new TruncatedSeq(TruncatedSeqLength)),
   _os_load_seq(new TruncatedSeq(TruncatedSeqLength)),
   _gc_count_seq(new TruncatedSeq(TruncatedSeqLength)),
   _prev_collection_pause_end_ms(0.0),
@@ -112,11 +111,9 @@ G1CollectorPolicy::G1CollectorPolicy() :
   _pause_time_target_ms((double) MaxGCPauseMillis),
 
   _gcs_are_young(true),
-  _periodic_gc(false),
   _last_uncommit_attempt_s(0.0),
   _os_load(-1.0),
   _uncommit_start_time(0),
-  _gc_count_cancel_extract(false),
   _gc_count(0),
   _gc_count_minute(0),
 
@@ -160,7 +157,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
   _inc_cset_predicted_elapsed_time_ms(0.0),
   _inc_cset_predicted_elapsed_time_ms_diffs(0.0),
   _collection_pause_end_millis(os::javaTimeNanos() / NANOSECS_PER_MILLISEC),
-  _extract_uncommit_list(0),
 #ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
 #pragma warning( disable:4355 ) // 'this' : used in base member initializer list
 #endif // _MSC_VER
@@ -1211,8 +1207,6 @@ void G1CollectorPolicy::record_heap_size_info_at_start(bool full) {
   _heap_capacity_bytes_before_gc = _g1->capacity();
   _heap_used_bytes_before_gc = _g1->used();
   _cur_collection_pause_used_regions_at_start = _g1->num_used_regions();
-  _heap_size_seq->add(_cur_collection_pause_used_regions_at_start);
-
   _eden_capacity_bytes_before_gc =
          (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc;
 
@@ -1255,13 +1249,6 @@ void G1CollectorPolicy::print_detailed_heap_transition(bool full) {
     EXT_SIZE_PARAMS(heap_used_bytes_after_gc),
     EXT_SIZE_PARAMS(heap_capacity_bytes_after_gc));
 
-  if (_extract_uncommit_list) {
-    gclog_or_tty->print(" [Uncommit list " UINT32_FORMAT ", remaining " UINT32_FORMAT ", free list " UINT32_FORMAT "]",
-                        _extract_uncommit_list,
-                        _g1->_hrm.length(),
-                        _g1->_hrm.num_free_regions());
-    _extract_uncommit_list = 0;
-  }
   if (full) {
     MetaspaceAux::print_metaspace_change(_metaspace_used_bytes_before_gc);
   }
@@ -2175,53 +2162,6 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms, EvacuationInf
   evacuation_info.set_collectionset_regions(cset_region_length());
 }
 
-void G1CollectorPolicy::record_gc_start(double curr_sec) {
-  if (_uncommit_start_time == 0) {
-    _uncommit_start_time = curr_sec + G1UncommitDelay;
-  }
-  long curr = curr_sec / 60;
-  if (curr > _gc_count_minute) {
-    int diff = curr - _gc_count_minute;
-    _gc_count_seq->add(_gc_count);
-    for (int i = 1; i < diff; i++) {
-      _gc_count_seq->add(0.0);
-    }
-    _gc_count_minute = curr;
-    double gc_count_expected = get_new_prediction(_gc_count_seq);
-    // Considering the test result, 15000 is an appropriate value for G1PeriodicGCInterval.
-    _gc_count_cancel_extract = gc_count_expected > MIN2(4.0, 60000.0 / G1PeriodicGCInterval);
-    _gc_count = 0;
-  }
-  _gc_count++;
-}
-
-bool G1CollectorPolicy::should_trigger_periodic_gc() {
-  if (G1PeriodicGCLoadThreshold && _os_load > G1PeriodicGCLoadThreshold) {
-    _periodic_gc = false;
-  } else if (_periodic_gc) {
-    _periodic_gc = false;
-    return true;
-  }
-  return false;
-}
-
-bool G1CollectorPolicy::can_extract_uncommit_list() {
-  double now = os::elapsedTime();
-  if (G1Uncommit && now > _uncommit_start_time) {
-    if (G1PeriodicGCLoadThreshold && _os_load > G1PeriodicGCLoadThreshold) {
-      return false;
-    }
-    G1CollectedHeap* g1h = G1CollectedHeap::heap();
-    if (!_gc_count_cancel_extract || now >= (g1h->millis_since_last_gc() + G1PeriodicGCInterval) / 1000.0) {
-      if (now - _last_uncommit_attempt_s >= G1PeriodicGCInterval / 1000.0) {
-        _last_uncommit_attempt_s = now;
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
 void TraceGen0TimeData::record_start_collection(double time_to_stop_the_world_ms) {
   if(TraceGen0Time) {
     _all_stop_world_times_ms.add(time_to_stop_the_world_ms);
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
index 1a0d20d6f..af5d5d57a 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
@@ -244,7 +244,6 @@ private:
   TruncatedSeq* _constant_other_time_ms_seq;
   TruncatedSeq* _young_other_cost_per_region_ms_seq;
   TruncatedSeq* _non_young_other_cost_per_region_ms_seq;
-  TruncatedSeq* _heap_size_seq;
   TruncatedSeq* _os_load_seq;
   TruncatedSeq* _gc_count_seq;
 
@@ -268,8 +267,6 @@ private:
 
   uint _free_regions_at_end_of_collection;
 
-  uint _extract_uncommit_list;
-
   size_t _recorded_rs_lengths;
   size_t _max_rs_lengths;
   double _sigma;
@@ -308,19 +305,12 @@ private:
 
   size_t _gc_count;
   long _gc_count_minute;
-  bool _gc_count_cancel_extract;
 
-  volatile bool _periodic_gc;
   double _last_uncommit_attempt_s;
   volatile double _os_load;
   double _uncommit_start_time;
 public:
   // Accessors
-
-  void set_periodic_gc() { _periodic_gc = true; }
-  bool can_extract_uncommit_list();
-  bool should_trigger_periodic_gc();
-
   void set_region_eden(HeapRegion* hr, int young_index_in_cset) {
     hr->set_eden();
     hr->install_surv_rate_group(_short_lived_surv_rate_group);
@@ -346,16 +336,14 @@ public:
     _max_rs_lengths = rs_lengths;
   }
 
-  size_t predict_heap_size_seq() {
-    return (size_t) get_new_prediction(_heap_size_seq);
-  }
-
   void add_os_load(double load) {
     _os_load_seq->add(load);
     _os_load = get_new_prediction(_os_load_seq);
   }
 
-  void record_gc_start(double sec);
+  double os_load() {
+    return _os_load;
+  }
 
   size_t predict_rs_length_diff() {
     return (size_t) get_new_prediction(_rs_length_diff_seq);
@@ -739,8 +727,6 @@ public:
   void record_stop_world_start();
   void record_concurrent_pause();
 
-  void record_extract_uncommit_list(uint count) { _extract_uncommit_list = count; }
-
   // Record how much space we copied during a GC. This is typically
   // called when a GC alloc region is being retired.
   void record_bytes_copied_during_gc(size_t bytes) {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1UncommitThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1UncommitThread.cpp
index 37bdbdb69..503218917 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1UncommitThread.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1UncommitThread.cpp
@@ -26,6 +26,9 @@
 
 #include "gc_implementation/g1/g1UncommitThread.hpp"
 #include "gc_implementation/g1/g1_globals.hpp"
+#include "gc_implementation/g1/g1Log.hpp"
+#include "gc_implementation/g1/g1CollectorPolicy.hpp"
+#include "gc_implementation/g1/concurrentMarkThread.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/os.hpp"
 
@@ -104,9 +107,12 @@ void PeriodicGC::start() {
 }
 
 void PeriodicGC::timer_thread_entry(JavaThread* thread, TRAPS) {
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
   while(!_should_terminate) {
     assert(!SafepointSynchronize::is_at_safepoint(), "PeriodicGC timer thread is a JavaThread");
-    G1CollectedHeap::heap()->check_trigger_periodic_gc();
+    if (check_for_periodic_gc()) {
+      g1h->collect(GCCause::_g1_periodic_collection);
+    }
 
     MutexLockerEx x(_monitor);
     if (_should_terminate) {
@@ -116,6 +122,78 @@ void PeriodicGC::timer_thread_entry(JavaThread* thread, TRAPS) {
   }
 }
 
+bool PeriodicGC::check_for_periodic_gc() {
+  if (!G1Uncommit) {
+    return false;
+  }
+
+  return should_start_periodic_gc();
+}
+
+bool PeriodicGC::should_start_periodic_gc() {
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  G1CollectorPolicy* g1p = g1h->g1_policy();
+  // If we are currently in a concurrent mark we are going to uncommit memory soon.
+  if (g1h->concurrent_mark()->cmThread()->during_cycle()) {
+    if (G1UncommitLog && G1Log::finest()) {
+      gclog_or_tty->date_stamp(PrintGCDateStamps);
+      gclog_or_tty->stamp(PrintGCTimeStamps);
+      gclog_or_tty->print_cr("[G1Uncommit] Concurrent cycle in progress. Skipping.");
+    }
+    return false;
+  }
+
+  // Check if enough time has passed since the last GC.
+  uintx time_since_last_gc = (uintx)Universe::heap()->millis_since_last_gc();
+  if (time_since_last_gc < G1PeriodicGCInterval) {
+    if (G1UncommitLog && G1Log::finest()) {
+      gclog_or_tty->date_stamp(PrintGCDateStamps);
+      gclog_or_tty->stamp(PrintGCTimeStamps);
+      gclog_or_tty->print_cr("[G1Uncommit] Last GC occurred " UINTX_FORMAT "ms before which is below threshold"
+                              UINTX_FORMAT "ms. Skipping.", time_since_last_gc, G1PeriodicGCInterval);
+    }
+    return false;
+  }
+
+  // Collect load need G1PeriodicGCInterval time after previous GC's end
+  assert(G1PeriodicGCInterval > 0, "just checking");
+  double recent_load = -1.0;
+
+  if (G1PeriodicGCLoadThreshold) {
+    // Sample process load and store it
+    if (G1PeriodicGCProcessLoad) {
+      recent_load = os::get_process_load() * 100;
+    }
+    if (recent_load < 0) {
+      // Fallback to os load
+      G1PeriodicGCProcessLoad = false;
+      if (os::loadavg(&recent_load, 1) != -1) {
+        static int cpu_count = os::active_processor_count();
+        assert(cpu_count > 0, "just checking");
+        recent_load = recent_load * 100 / cpu_count;
+      }
+    }
+    if (recent_load >= 0) {
+      g1p->add_os_load(recent_load);
+    }
+  }
+
+  if (G1UncommitLog) {
+    gclog_or_tty->date_stamp(PrintGCDateStamps);
+    gclog_or_tty->stamp(PrintGCTimeStamps);
+    recent_load < 0 ? gclog_or_tty->print_cr("[G1Uncommit] Checking for periodic GC.")
+                    : gclog_or_tty->print_cr("[G1Uncommit] Checking for periodic GC. Current load %1.2f. "
+                                             "total regions: " UINT32_FORMAT" free regions: " UINT32_FORMAT,
+                                            recent_load, g1h->num_regions(), g1h->num_free_regions());
+  }
+
+  if (g1p->os_load() < G1PeriodicGCLoadThreshold || !G1PeriodicGCLoadThreshold) {
+    return true;
+  }
+  gclog_or_tty->print_cr("[G1Uncommit] Periodic GC request denied, skipping!");
+  return false;
+}
+
 void PeriodicGC::stop() {
   _should_terminate = true;
   {
@@ -139,7 +217,7 @@ G1UncommitThread::G1UncommitThread() :
     }
   }
   if (G1UncommitLog) {
-    gclog_or_tty->print_cr("Periodic GC Thread start");
+    gclog_or_tty->print_cr("[G1Uncommit] Periodic GC Thread start");
   }
 }
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1UncommitThread.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1UncommitThread.hpp
index 883a9a418..6f1d5e35f 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1UncommitThread.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1UncommitThread.hpp
@@ -40,6 +40,8 @@ public:
   static void         start();
   static void         stop();
   static bool         has_error(TRAPS, const char* error);
+  static bool         check_for_periodic_gc();
+  static bool         should_start_periodic_gc();
 };
 
 class G1UncommitThread: public ConcurrentGCThread {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp
index 56e2d32df..d31073f9f 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp
@@ -573,21 +573,23 @@ void HeapRegionManager::free_uncommit_list_memory() {
   }
 }
 
-uint HeapRegionManager::extract_uncommit_list()
-{
+uint HeapRegionManager::extract_uncommit_list(uint num_candidate_to_remove) {
   assert_at_safepoint(true /* should_be_vm_thread */);
+  double start_up_sec = os::elapsedTime();
+  if (start_up_sec < G1UncommitDelay) {
+    gclog_or_tty->date_stamp(PrintGCDateStamps);
+    gclog_or_tty->stamp(PrintGCTimeStamps);
+    gclog_or_tty->print_cr("start up seconds:%lf, less than G1UncommitDelay, will not uncommit.", start_up_sec);
+    return 0;
+  }
+
   if (!_uncommit_list_filled) {
-    G1CollectedHeap* g1h = G1CollectedHeap::heap();
-    uint dest = ((G1CollectorPolicy*)g1h->collector_policy())->predict_heap_size_seq();
-
-    if (dest < _num_committed) {
-      uint num_regions_to_remove = (_num_committed - dest) * G1UncommitPercent;
-      if (num_regions_to_remove >= 1 && num_regions_to_remove < _free_list.length()) {
-        int count = _free_list.move_regions_to(&_uncommit_list, num_regions_to_remove);
-        OrderAccess::storestore();
-        _uncommit_list_filled = true;
-        return count;
-      }
+    uint num_regions_to_remove = num_candidate_to_remove * G1UncommitPercent;
+    if (num_regions_to_remove >= 1 && num_regions_to_remove < _free_list.length()) {
+      int count = _free_list.move_regions_to(&_uncommit_list, num_regions_to_remove);
+      OrderAccess::storestore();
+      _uncommit_list_filled = true;
+      return count;
     }
   }
   return 0;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp
index 25f3a223f..3950d6280 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp
@@ -175,7 +175,7 @@ public:
                   G1RegionToSpaceMapper* cardtable,
                   G1RegionToSpaceMapper* card_counts);
 
-  uint extract_uncommit_list();
+  uint extract_uncommit_list(uint num_candidate_to_remove);
   void free_uncommit_list_memory();
 
   // Return the "dummy" region used for G1AllocRegion. This is currently a hardwired
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.inline.hpp
index 68840d61e..50d0fa832 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.inline.hpp
@@ -40,8 +40,8 @@ inline HeapRegion* HeapRegionManager::addr_to_region(HeapWord* addr) const {
 }
 
 inline HeapRegion* HeapRegionManager::at(uint index) const {
-  assert(is_available(index), "pre-condition");
   HeapRegion* hr = _regions.get_by_index(index);
+  assert(hr->in_uncommit_list() || is_available(index), "pre-condition");
   assert(hr != NULL, "sanity");
   assert(hr->hrm_index() == index, "sanity");
   return hr;
-- 
2.22.0

