8212206: Refactor AdaptiveSizePolicy to separate out code related to GC overhead
authormanc
Tue, 15 Jan 2019 15:59:47 -0800
changeset 54085 ab87b06dfdc0
parent 54084 84f10bbf993f
child 54086 ccb4a50bee06
8212206: Refactor AdaptiveSizePolicy to separate out code related to GC overhead Summary: Move check_gc_overhead_limit() and related code to its own class Reviewed-by: tschatzl, pliden, jiangli
src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp
src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.cpp
src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp
src/hotspot/share/gc/parallel/psMarkSweep.cpp
src/hotspot/share/gc/parallel/psParallelCompact.cpp
src/hotspot/share/gc/parallel/psScavenge.cpp
src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp
src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp
src/hotspot/share/gc/shared/gcOverheadChecker.cpp
src/hotspot/share/gc/shared/gcOverheadChecker.hpp
src/hotspot/share/gc/shared/gcPolicyCounters.cpp
src/hotspot/share/gc/shared/gcPolicyCounters.hpp
src/hotspot/share/gc/shared/gc_globals.hpp
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Tue Jan 15 15:59:47 2019 -0800
@@ -1498,8 +1498,7 @@
   // Has the GC time limit been exceeded?
   size_t max_eden_size = _young_gen->max_eden_size();
   GCCause::Cause gc_cause = heap->gc_cause();
-  size_policy()->check_gc_overhead_limit(_young_gen->used(),
-                                         _young_gen->eden()->used(),
+  size_policy()->check_gc_overhead_limit(_young_gen->eden()->used(),
                                          _cmsGen->max_capacity(),
                                          max_eden_size,
                                          full,
--- a/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.cpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.cpp	Tue Jan 15 15:59:47 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -118,11 +118,6 @@
     _avg_base_footprint = PerfDataManager::create_variable(SUN_GC, cname,
       PerfData::U_Bytes, (jlong) ps_size_policy()->avg_base_footprint()->average(), CHECK);
 
-    cname = PerfDataManager::counter_name(name_space(), "gcTimeLimitExceeded");
-    _gc_overhead_limit_exceeded_counter =
-      PerfDataManager::create_variable(SUN_GC, cname,
-      PerfData::U_Events, ps_size_policy()->gc_overhead_limit_exceeded(), CHECK);
-
     cname = PerfDataManager::counter_name(name_space(), "liveAtLastFullGc");
     _live_at_last_full_gc_counter =
       PerfDataManager::create_variable(SUN_GC, cname,
--- a/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psGCAdaptivePolicyCounters.hpp	Tue Jan 15 15:59:47 2019 -0800
@@ -51,7 +51,6 @@
   PerfVariable* _live_space;
   PerfVariable* _free_space;
   PerfVariable* _avg_base_footprint;
-  PerfVariable* _gc_overhead_limit_exceeded_counter;
   PerfVariable* _live_at_last_full_gc_counter;
   PerfVariable* _old_capacity;
   PerfVariable* _boundary_moved;
@@ -177,7 +176,7 @@
     );
   }
   inline void update_gc_overhead_limit_exceeded_counter() {
-    _gc_overhead_limit_exceeded_counter->set_value(
+    gc_overhead_limit_exceeded_counter()->set_value(
       (jlong) ps_size_policy()->gc_overhead_limit_exceeded());
   }
   inline void update_live_at_last_full_gc_counter() {
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Tue Jan 15 15:59:47 2019 -0800
@@ -316,8 +316,7 @@
                                                     max_eden_size,
                                                     true /* full gc*/);
 
-        size_policy->check_gc_overhead_limit(young_live,
-                                             eden_live,
+        size_policy->check_gc_overhead_limit(eden_live,
                                              max_old_gen_size,
                                              max_eden_size,
                                              true /* full gc*/,
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Tue Jan 15 15:59:47 2019 -0800
@@ -1889,8 +1889,7 @@
                                                     max_eden_size,
                                                     true /* full gc*/);
 
-        size_policy->check_gc_overhead_limit(young_live,
-                                             eden_live,
+        size_policy->check_gc_overhead_limit(eden_live,
                                              max_old_gen_size,
                                              max_eden_size,
                                              true /* full gc*/,
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp	Tue Jan 15 15:59:47 2019 -0800
@@ -537,8 +537,7 @@
                                                max_eden_size,
                                                false /* not full gc*/);
 
-          size_policy->check_gc_overhead_limit(young_live,
-                                               eden_live,
+          size_policy->check_gc_overhead_limit(eden_live,
                                                max_old_gen_size,
                                                max_eden_size,
                                                false /* not full gc*/,
--- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp	Tue Jan 15 15:59:47 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, 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
@@ -26,7 +26,6 @@
 #include "gc/shared/adaptiveSizePolicy.hpp"
 #include "gc/shared/gcCause.hpp"
 #include "gc/shared/gcUtil.inline.hpp"
-#include "gc/shared/softRefPolicy.hpp"
 #include "logging/log.hpp"
 #include "runtime/timer.hpp"
 
@@ -49,16 +48,11 @@
     _eden_size(init_eden_size),
     _promo_size(init_promo_size),
     _survivor_size(init_survivor_size),
-    _gc_overhead_limit_exceeded(false),
-    _print_gc_overhead_limit_would_be_exceeded(false),
-    _gc_overhead_limit_count(0),
     _latest_minor_mutator_interval_seconds(0),
     _threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0),
     _gc_pause_goal_sec(gc_pause_goal_sec),
     _young_gen_change_for_minor_throughput(0),
     _old_gen_change_for_major_throughput(0) {
-  assert(AdaptiveSizePolicyGCTimeLimitThreshold > 0,
-    "No opportunity to clear SoftReferences before GC overhead limit");
   _avg_minor_pause    =
     new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
   _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
@@ -277,8 +271,90 @@
   set_decide_at_full_gc(0);
 }
 
+class AdaptiveSizePolicyTimeOverheadTester: public GCOverheadTester {
+  double _gc_cost;
+
+ public:
+  AdaptiveSizePolicyTimeOverheadTester(double gc_cost) : _gc_cost(gc_cost) {}
+
+  bool is_exceeded() {
+    return _gc_cost > (GCTimeLimit / 100.0);
+  }
+};
+
+class AdaptiveSizePolicySpaceOverheadTester: public GCOverheadTester {
+  size_t _eden_live;
+  size_t _max_old_gen_size;
+  size_t _max_eden_size;
+  size_t _promo_size;
+  double _avg_eden_live;
+  double _avg_old_live;
+
+ public:
+  AdaptiveSizePolicySpaceOverheadTester(size_t eden_live,
+                                        size_t max_old_gen_size,
+                                        size_t max_eden_size,
+                                        size_t promo_size,
+                                        double avg_eden_live,
+                                        double avg_old_live) :
+    _eden_live(eden_live),
+    _max_old_gen_size(max_old_gen_size),
+    _max_eden_size(max_eden_size),
+    _promo_size(promo_size),
+    _avg_eden_live(avg_eden_live),
+    _avg_old_live(avg_old_live) {}
+
+  bool is_exceeded() {
+    // _max_eden_size is the upper limit on the size of eden based on
+    // the maximum size of the young generation and the sizes
+    // of the survivor space.
+    // The question being asked is whether the space being recovered by
+    // a collection is low.
+    // free_in_eden is the free space in eden after a collection and
+    // free_in_old_gen is the free space in the old generation after
+    // a collection.
+    //
+    // Use the minimum of the current value of the live in eden
+    // or the average of the live in eden.
+    // If the current value drops quickly, that should be taken
+    // into account (i.e., don't trigger if the amount of free
+    // space has suddenly jumped up).  If the current is much
+    // higher than the average, use the average since it represents
+    // the longer term behavior.
+    const size_t live_in_eden =
+      MIN2(_eden_live, (size_t)_avg_eden_live);
+    const size_t free_in_eden = _max_eden_size > live_in_eden ?
+      _max_eden_size - live_in_eden : 0;
+    const size_t free_in_old_gen = (size_t)(_max_old_gen_size - _avg_old_live);
+    const size_t total_free_limit = free_in_old_gen + free_in_eden;
+    const size_t total_mem = _max_old_gen_size + _max_eden_size;
+    const double free_limit_ratio = GCHeapFreeLimit / 100.0;
+    const double mem_free_limit = total_mem * free_limit_ratio;
+    const double mem_free_old_limit = _max_old_gen_size * free_limit_ratio;
+    const double mem_free_eden_limit = _max_eden_size * free_limit_ratio;
+    size_t promo_limit = (size_t)(_max_old_gen_size - _avg_old_live);
+    // But don't force a promo size below the current promo size. Otherwise,
+    // the promo size will shrink for no good reason.
+    promo_limit = MAX2(promo_limit, _promo_size);
+
+    log_trace(gc, ergo)(
+          "AdaptiveSizePolicySpaceOverheadTester::is_exceeded:"
+          " promo_limit: " SIZE_FORMAT
+          " max_eden_size: " SIZE_FORMAT
+          " total_free_limit: " SIZE_FORMAT
+          " max_old_gen_size: " SIZE_FORMAT
+          " max_eden_size: " SIZE_FORMAT
+          " mem_free_limit: " SIZE_FORMAT,
+          promo_limit, _max_eden_size, total_free_limit,
+          _max_old_gen_size, _max_eden_size,
+          (size_t)mem_free_limit);
+
+    return free_in_old_gen < (size_t)mem_free_old_limit &&
+           free_in_eden < (size_t)mem_free_eden_limit;
+  }
+};
+
 void AdaptiveSizePolicy::check_gc_overhead_limit(
-                                          size_t young_live,
                                           size_t eden_live,
                                           size_t max_old_gen_size,
                                           size_t max_eden_size,
@@ -286,128 +362,18 @@
                                           GCCause::Cause gc_cause,
                                           SoftRefPolicy* soft_ref_policy) {
 
-  // Ignore explicit GC's.  Exiting here does not set the flag and
-  // does not reset the count.  Updating of the averages for system
-  // GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC.
-  if (GCCause::is_user_requested_gc(gc_cause) ||
-      GCCause::is_serviceability_requested_gc(gc_cause)) {
-    return;
-  }
-  // eden_limit is the upper limit on the size of eden based on
-  // the maximum size of the young generation and the sizes
-  // of the survivor space.
-  // The question being asked is whether the gc costs are high
-  // and the space being recovered by a collection is low.
-  // free_in_young_gen is the free space in the young generation
-  // after a collection and promo_live is the free space in the old
-  // generation after a collection.
-  //
-  // Use the minimum of the current value of the live in the
-  // young gen or the average of the live in the young gen.
-  // If the current value drops quickly, that should be taken
-  // into account (i.e., don't trigger if the amount of free
-  // space has suddenly jumped up).  If the current is much
-  // higher than the average, use the average since it represents
-  // the longer term behavior.
-  const size_t live_in_eden =
-    MIN2(eden_live, (size_t) avg_eden_live()->average());
-  const size_t free_in_eden = max_eden_size > live_in_eden ?
-    max_eden_size - live_in_eden : 0;
-  const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());
-  const size_t total_free_limit = free_in_old_gen + free_in_eden;
-  const size_t total_mem = max_old_gen_size + max_eden_size;
-  const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0);
-  const double mem_free_old_limit = max_old_gen_size * (GCHeapFreeLimit/100.0);
-  const double mem_free_eden_limit = max_eden_size * (GCHeapFreeLimit/100.0);
-  const double gc_cost_limit = GCTimeLimit/100.0;
-  size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average());
-  // But don't force a promo size below the current promo size. Otherwise,
-  // the promo size will shrink for no good reason.
-  promo_limit = MAX2(promo_limit, _promo_size);
-
-
-  log_trace(gc, ergo)(
-        "PSAdaptiveSizePolicy::check_gc_overhead_limit:"
-        " promo_limit: " SIZE_FORMAT
-        " max_eden_size: " SIZE_FORMAT
-        " total_free_limit: " SIZE_FORMAT
-        " max_old_gen_size: " SIZE_FORMAT
-        " max_eden_size: " SIZE_FORMAT
-        " mem_free_limit: " SIZE_FORMAT,
-        promo_limit, max_eden_size, total_free_limit,
-        max_old_gen_size, max_eden_size,
-        (size_t) mem_free_limit);
-
-  bool print_gc_overhead_limit_would_be_exceeded = false;
-  if (is_full_gc) {
-    if (gc_cost() > gc_cost_limit &&
-      free_in_old_gen < (size_t) mem_free_old_limit &&
-      free_in_eden < (size_t) mem_free_eden_limit) {
-      // Collections, on average, are taking too much time, and
-      //      gc_cost() > gc_cost_limit
-      // we have too little space available after a full gc.
-      //      total_free_limit < mem_free_limit
-      // where
-      //   total_free_limit is the free space available in
-      //     both generations
-      //   total_mem is the total space available for allocation
-      //     in both generations (survivor spaces are not included
-      //     just as they are not included in eden_limit).
-      //   mem_free_limit is a fraction of total_mem judged to be an
-      //     acceptable amount that is still unused.
-      // The heap can ask for the value of this variable when deciding
-      // whether to thrown an OutOfMemory error.
-      // Note that the gc time limit test only works for the collections
-      // of the young gen + tenured gen and not for collections of the
-      // permanent gen.  That is because the calculation of the space
-      // freed by the collection is the free space in the young gen +
-      // tenured gen.
-      // At this point the GC overhead limit is being exceeded.
-      inc_gc_overhead_limit_count();
-      if (UseGCOverheadLimit) {
-        if (gc_overhead_limit_count() >=
-            AdaptiveSizePolicyGCTimeLimitThreshold){
-          // All conditions have been met for throwing an out-of-memory
-          set_gc_overhead_limit_exceeded(true);
-          // Avoid consecutive OOM due to the gc time limit by resetting
-          // the counter.
-          reset_gc_overhead_limit_count();
-        } else {
-          // The required consecutive collections which exceed the
-          // GC time limit may or may not have been reached. We
-          // are approaching that condition and so as not to
-          // throw an out-of-memory before all SoftRef's have been
-          // cleared, set _should_clear_all_soft_refs in CollectorPolicy.
-          // The clearing will be done on the next GC.
-          bool near_limit = gc_overhead_limit_near();
-          if (near_limit) {
-            soft_ref_policy->set_should_clear_all_soft_refs(true);
-            log_trace(gc, ergo)("Nearing GC overhead limit, will be clearing all SoftReference");
-          }
-        }
-      }
-      // Set this even when the overhead limit will not
-      // cause an out-of-memory.  Diagnostic message indicating
-      // that the overhead limit is being exceeded is sometimes
-      // printed.
-      print_gc_overhead_limit_would_be_exceeded = true;
-
-    } else {
-      // Did not exceed overhead limits
-      reset_gc_overhead_limit_count();
-    }
-  }
-
-  if (UseGCOverheadLimit) {
-    if (gc_overhead_limit_exceeded()) {
-      log_trace(gc, ergo)("GC is exceeding overhead limit of " UINTX_FORMAT "%%", GCTimeLimit);
-      reset_gc_overhead_limit_count();
-    } else if (print_gc_overhead_limit_would_be_exceeded) {
-      assert(gc_overhead_limit_count() > 0, "Should not be printing");
-      log_trace(gc, ergo)("GC would exceed overhead limit of " UINTX_FORMAT "%% %d consecutive time(s)",
-                          GCTimeLimit, gc_overhead_limit_count());
-    }
-  }
+  AdaptiveSizePolicyTimeOverheadTester time_overhead(gc_cost());
+  AdaptiveSizePolicySpaceOverheadTester space_overhead(eden_live,
+                                                       max_old_gen_size,
+                                                       max_eden_size,
+                                                       _promo_size,
+                                                       avg_eden_live()->average(),
+                                                       avg_old_live()->average());
+  _overhead_checker.check_gc_overhead_limit(&time_overhead,
+                                            &space_overhead,
+                                            is_full_gc,
+                                            gc_cause,
+                                            soft_ref_policy);
 }
 // Printing
 
--- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp	Tue Jan 15 15:59:47 2019 -0800
@@ -26,6 +26,7 @@
 #define SHARE_GC_SHARED_ADAPTIVESIZEPOLICY_HPP
 
 #include "gc/shared/gcCause.hpp"
+#include "gc/shared/gcOverheadChecker.hpp"
 #include "gc/shared/gcUtil.hpp"
 #include "memory/allocation.hpp"
 
@@ -34,7 +35,6 @@
 
 // Forward decls
 class elapsedTimer;
-class SoftRefPolicy;
 
 class AdaptiveSizePolicy : public CHeapObj<mtGC> {
  friend class GCAdaptivePolicyCounters;
@@ -81,18 +81,8 @@
 
   size_t _survivor_size;    // calculated survivor size in bytes
 
-  // This is a hint for the heap:  we've detected that GC times
-  // are taking longer than GCTimeLimit allows.
-  bool _gc_overhead_limit_exceeded;
-  // Use for diagnostics only.  If UseGCOverheadLimit is false,
-  // this variable is still set.
-  bool _print_gc_overhead_limit_would_be_exceeded;
-  // Count of consecutive GC that have exceeded the
-  // GC time limit criterion
-  uint _gc_overhead_limit_count;
-  // This flag signals that GCTimeLimit is being exceeded
-  // but may not have done so for the required number of consecutive
-  // collections
+  // Support for UseGCOverheadLimit
+  GCOverheadChecker _overhead_checker;
 
   // Minor collection timers used to determine both
   // pause and interval times for collections
@@ -412,26 +402,20 @@
     return _survivor_size;
   }
 
-  // This is a hint for the heap:  we've detected that gc times
-  // are taking longer than GCTimeLimit allows.
-  // Most heaps will choose to throw an OutOfMemoryError when
-  // this occurs but it is up to the heap to request this information
-  // of the policy
   bool gc_overhead_limit_exceeded() {
-    return _gc_overhead_limit_exceeded;
+    return _overhead_checker.gc_overhead_limit_exceeded();
   }
   void set_gc_overhead_limit_exceeded(bool v) {
-    _gc_overhead_limit_exceeded = v;
+    _overhead_checker.set_gc_overhead_limit_exceeded(v);
   }
 
-  // Tests conditions indicate the GC overhead limit is being approached.
   bool gc_overhead_limit_near() {
-    return gc_overhead_limit_count() >=
-        (AdaptiveSizePolicyGCTimeLimitThreshold - 1);
+    return _overhead_checker.gc_overhead_limit_near();
   }
-  uint gc_overhead_limit_count() { return _gc_overhead_limit_count; }
-  void reset_gc_overhead_limit_count() { _gc_overhead_limit_count = 0; }
-  void inc_gc_overhead_limit_count() { _gc_overhead_limit_count++; }
+
+  void reset_gc_overhead_limit_count() {
+    _overhead_checker.reset_gc_overhead_limit_count();
+  }
   // accessors for flags recording the decisions to resize the
   // generations to meet the pause goal.
 
@@ -448,8 +432,7 @@
 
   // Check the conditions for an out-of-memory due to excessive GC time.
   // Set _gc_overhead_limit_exceeded if all the conditions have been met.
-  void check_gc_overhead_limit(size_t young_live,
-                               size_t eden_live,
+  void check_gc_overhead_limit(size_t eden_live,
                                size_t max_old_gen_size,
                                size_t max_eden_size,
                                bool   is_full_gc,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gcOverheadChecker.cpp	Tue Jan 15 15:59:47 2019 -0800
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Google 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/gcOverheadChecker.hpp"
+#include "gc/shared/softRefPolicy.hpp"
+#include "logging/log.hpp"
+
+GCOverheadChecker::GCOverheadChecker() :
+  _gc_overhead_limit_exceeded(false),
+  _print_gc_overhead_limit_would_be_exceeded(false),
+  _gc_overhead_limit_count(0) {
+  assert(GCOverheadLimitThreshold > 0,
+    "No opportunity to clear SoftReferences before GC overhead limit");
+}
+
+void GCOverheadChecker::check_gc_overhead_limit(GCOverheadTester* time_overhead,
+                                                GCOverheadTester* space_overhead,
+                                                bool is_full_gc,
+                                                GCCause::Cause gc_cause,
+                                                SoftRefPolicy* soft_ref_policy) {
+
+  // Ignore explicit GC's.  Exiting here does not set the flag and
+  // does not reset the count.
+  if (GCCause::is_user_requested_gc(gc_cause) ||
+      GCCause::is_serviceability_requested_gc(gc_cause)) {
+    return;
+  }
+
+  bool print_gc_overhead_limit_would_be_exceeded = false;
+  if (is_full_gc) {
+    if (time_overhead->is_exceeded() && space_overhead->is_exceeded()) {
+      // Collections, on average, are taking too much time, and
+      // we have too little space available after a full gc.
+      // At this point the GC overhead limit is being exceeded.
+      _gc_overhead_limit_count++;
+      if (UseGCOverheadLimit) {
+        if (_gc_overhead_limit_count >= GCOverheadLimitThreshold){
+          // All conditions have been met for throwing an out-of-memory
+          set_gc_overhead_limit_exceeded(true);
+          // Avoid consecutive OOM due to the gc time limit by resetting
+          // the counter.
+          reset_gc_overhead_limit_count();
+        } else {
+          // The required consecutive collections which exceed the
+          // GC time limit may or may not have been reached. We
+          // are approaching that condition and so as not to
+          // throw an out-of-memory before all SoftRef's have been
+          // cleared, set _should_clear_all_soft_refs in CollectorPolicy.
+          // The clearing will be done on the next GC.
+          bool near_limit = gc_overhead_limit_near();
+          if (near_limit) {
+            soft_ref_policy->set_should_clear_all_soft_refs(true);
+            log_trace(gc, ergo)("Nearing GC overhead limit, will be clearing all SoftReference");
+          }
+        }
+      }
+      // Set this even when the overhead limit will not
+      // cause an out-of-memory.  Diagnostic message indicating
+      // that the overhead limit is being exceeded is sometimes
+      // printed.
+      print_gc_overhead_limit_would_be_exceeded = true;
+
+    } else {
+      // Did not exceed overhead limits
+      reset_gc_overhead_limit_count();
+    }
+  }
+
+  if (UseGCOverheadLimit) {
+    if (gc_overhead_limit_exceeded()) {
+      log_trace(gc, ergo)("GC is exceeding overhead limit of " UINTX_FORMAT "%%", GCTimeLimit);
+      reset_gc_overhead_limit_count();
+    } else if (print_gc_overhead_limit_would_be_exceeded) {
+      assert(_gc_overhead_limit_count > 0, "Should not be printing");
+      log_trace(gc, ergo)("GC would exceed overhead limit of " UINTX_FORMAT "%% %d consecutive time(s)",
+                          GCTimeLimit, _gc_overhead_limit_count);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gcOverheadChecker.hpp	Tue Jan 15 15:59:47 2019 -0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Google 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_GCOVERHEADCHECKER_HPP
+#define SHARE_GC_SHARED_GCOVERHEADCHECKER_HPP
+
+#include "memory/allocation.hpp"
+#include "gc/shared/gcCause.hpp"
+
+class SoftRefPolicy;
+
+class GCOverheadTester: public StackObj {
+public:
+  virtual bool is_exceeded() = 0;
+};
+
+class GCOverheadChecker: public CHeapObj<mtGC> {
+  // This is a hint for the heap:  we've detected that GC times
+  // are taking longer than GCTimeLimit allows.
+  bool _gc_overhead_limit_exceeded;
+  // Use for diagnostics only.  If UseGCOverheadLimit is false,
+  // this variable is still set.
+  bool _print_gc_overhead_limit_would_be_exceeded;
+  // Count of consecutive GC that have exceeded the
+  // GC time limit criterion
+  uint _gc_overhead_limit_count;
+  // This flag signals that GCTimeLimit is being exceeded
+  // but may not have done so for the required number of consecutive
+  // collections
+
+public:
+  GCOverheadChecker();
+
+  // This is a hint for the heap:  we've detected that gc times
+  // are taking longer than GCTimeLimit allows.
+  // Most heaps will choose to throw an OutOfMemoryError when
+  // this occurs but it is up to the heap to request this information
+  // of the policy
+  bool gc_overhead_limit_exceeded() {
+    return _gc_overhead_limit_exceeded;
+  }
+  void set_gc_overhead_limit_exceeded(bool v) {
+    _gc_overhead_limit_exceeded = v;
+  }
+
+  // Tests conditions indicate the GC overhead limit is being approached.
+  bool gc_overhead_limit_near() {
+    return _gc_overhead_limit_count >= (GCOverheadLimitThreshold - 1);
+  }
+  void reset_gc_overhead_limit_count() {
+    _gc_overhead_limit_count = 0;
+  }
+
+  // Check the conditions for an out-of-memory due to excessive GC time.
+  // Set _gc_overhead_limit_exceeded if all the conditions have been met.
+  void check_gc_overhead_limit(GCOverheadTester* time_overhead,
+                               GCOverheadTester* space_overhead,
+                               bool is_full_gc,
+                               GCCause::Cause gc_cause,
+                               SoftRefPolicy* soft_ref_policy);
+};
+
+#endif // SHARE_GC_SHARED_GCOVERHEADCHECKER_HPP
--- a/src/hotspot/share/gc/shared/gcPolicyCounters.cpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcPolicyCounters.cpp	Tue Jan 15 15:59:47 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -59,5 +59,10 @@
     _desired_survivor_size =
         PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
                                          CHECK);
+
+    cname = PerfDataManager::counter_name(_name_space, "gcTimeLimitExceeded");
+    _gc_overhead_limit_exceeded_counter =
+        PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Events,
+                                         CHECK);
   }
 }
--- a/src/hotspot/share/gc/shared/gcPolicyCounters.hpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/gcPolicyCounters.hpp	Tue Jan 15 15:59:47 2019 -0800
@@ -41,6 +41,7 @@
 
   PerfVariable* _tenuring_threshold;
   PerfVariable* _desired_survivor_size;
+  PerfVariable* _gc_overhead_limit_exceeded_counter;
 
   const char* _name_space;
 
@@ -62,6 +63,10 @@
     return _desired_survivor_size;
   }
 
+  inline PerfVariable* gc_overhead_limit_exceeded_counter() const {
+    return _gc_overhead_limit_exceeded_counter;
+  }
+
   const char* name_space() const { return _name_space; }
 
   virtual void update_counters() {}
--- a/src/hotspot/share/gc/shared/gc_globals.hpp	Tue Mar 12 19:17:42 2019 +0100
+++ b/src/hotspot/share/gc/shared/gc_globals.hpp	Tue Jan 15 15:59:47 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -616,7 +616,7 @@
           "OutOfMemoryError is thrown (used with GCTimeLimit)")             \
           range(0, 100)                                                     \
                                                                             \
-  develop(uintx, AdaptiveSizePolicyGCTimeLimitThreshold, 5,                 \
+  develop(uintx, GCOverheadLimitThreshold, 5,                               \
           "Number of consecutive collections before gc time limit fires")   \
           range(1, max_uintx)                                               \
                                                                             \