1 /*
   2  * Copyright (c) 2013, 2018, Red Hat, Inc. and/or its affiliates.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "gc_implementation/shared/gcTimer.hpp"
  26 #include "gc_implementation/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp"
  27 #include "gc_implementation/shenandoah/heuristics/shenandoahAggressiveHeuristics.hpp"
  28 #include "gc_implementation/shenandoah/heuristics/shenandoahCompactHeuristics.hpp"
  29 #include "gc_implementation/shenandoah/heuristics/shenandoahPassiveHeuristics.hpp"
  30 #include "gc_implementation/shenandoah/heuristics/shenandoahStaticHeuristics.hpp"
  31 #include "gc_implementation/shenandoah/shenandoahCollectionSet.hpp"
  32 #include "gc_implementation/shenandoah/shenandoahCollectorPolicy.hpp"
  33 #include "gc_implementation/shenandoah/shenandoahFreeSet.hpp"
  34 #include "gc_implementation/shenandoah/shenandoahHeuristics.hpp"
  35 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
  36 #include "gc_implementation/shenandoah/shenandoahLogging.hpp"
  37 
  38 void ShenandoahCollectorPolicy::record_gc_start() {
  39   _heuristics->record_gc_start();
  40 }
  41 
  42 void ShenandoahCollectorPolicy::record_gc_end() {
  43   _heuristics->record_gc_end();
  44 }
  45 
  46 ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() :
  47   _cycle_counter(0),
  48   _success_concurrent_gcs(0),
  49   _success_partial_gcs(0),
  50   _success_degenerated_gcs(0),
  51   _success_full_gcs(0),
  52   _explicit_concurrent(0),
  53   _explicit_full(0),
  54   _alloc_failure_degenerated(0),
  55   _alloc_failure_full(0),
  56   _alloc_failure_degenerated_upgrade_to_full(0)
  57 {
  58   Copy::zero_to_bytes(_degen_points, sizeof(size_t) * ShenandoahHeap::_DEGENERATED_LIMIT);
  59 
  60   ShenandoahHeapRegion::setup_heap_region_size(initial_heap_byte_size(), max_heap_byte_size());
  61 
  62   initialize_all();
  63 
  64   _tracer = new (ResourceObj::C_HEAP, mtGC) ShenandoahTracer();
  65 
  66   if (ShenandoahGCHeuristics != NULL) {
  67     if (strcmp(ShenandoahGCHeuristics, "aggressive") == 0) {
  68       _heuristics = new ShenandoahAggressiveHeuristics();
  69     } else if (strcmp(ShenandoahGCHeuristics, "static") == 0) {
  70       _heuristics = new ShenandoahStaticHeuristics();
  71     } else if (strcmp(ShenandoahGCHeuristics, "adaptive") == 0) {
  72       _heuristics = new ShenandoahAdaptiveHeuristics();
  73     } else if (strcmp(ShenandoahGCHeuristics, "passive") == 0) {
  74       _heuristics = new ShenandoahPassiveHeuristics();
  75     } else if (strcmp(ShenandoahGCHeuristics, "compact") == 0) {
  76       _heuristics = new ShenandoahCompactHeuristics();
  77     } else {
  78       vm_exit_during_initialization("Unknown -XX:ShenandoahGCHeuristics option");
  79     }
  80 
  81     if (_heuristics->is_diagnostic() && !UnlockDiagnosticVMOptions) {
  82       vm_exit_during_initialization(
  83               err_msg("Heuristics \"%s\" is diagnostic, and must be enabled via -XX:+UnlockDiagnosticVMOptions.",
  84                       _heuristics->name()));
  85     }
  86     if (_heuristics->is_experimental() && !UnlockExperimentalVMOptions) {
  87       vm_exit_during_initialization(
  88               err_msg("Heuristics \"%s\" is experimental, and must be enabled via -XX:+UnlockExperimentalVMOptions.",
  89                       _heuristics->name()));
  90     }
  91     log_info(gc, init)("Shenandoah heuristics: %s",
  92                        _heuristics->name());
  93     _heuristics->print_thresholds();
  94   } else {
  95       ShouldNotReachHere();
  96   }
  97 }
  98 
  99 ShenandoahCollectorPolicy* ShenandoahCollectorPolicy::as_pgc_policy() {
 100   return this;
 101 }
 102 
 103 BarrierSet::Name ShenandoahCollectorPolicy::barrier_set_name() {
 104   return BarrierSet::ShenandoahBarrierSet;
 105 }
 106 
 107 HeapWord* ShenandoahCollectorPolicy::mem_allocate_work(size_t size,
 108                                                        bool is_tlab,
 109                                                        bool* gc_overhead_limit_was_exceeded) {
 110   guarantee(false, "Not using this policy feature yet.");
 111   return NULL;
 112 }
 113 
 114 HeapWord* ShenandoahCollectorPolicy::satisfy_failed_allocation(size_t size, bool is_tlab) {
 115   guarantee(false, "Not using this policy feature yet.");
 116   return NULL;
 117 }
 118 
 119 void ShenandoahCollectorPolicy::initialize_alignments() {
 120 
 121   // This is expected by our algorithm for ShenandoahHeap::heap_region_containing().
 122   _space_alignment = ShenandoahHeapRegion::region_size_bytes();
 123   _heap_alignment = ShenandoahHeapRegion::region_size_bytes();
 124 }
 125 
 126 void ShenandoahCollectorPolicy::post_heap_initialize() {
 127   // Nothing to do here (yet).
 128 }
 129 
 130 void ShenandoahCollectorPolicy::record_explicit_to_concurrent() {
 131   _heuristics->record_explicit_gc();
 132   _explicit_concurrent++;
 133 }
 134 
 135 void ShenandoahCollectorPolicy::record_explicit_to_full() {
 136   _heuristics->record_explicit_gc();
 137   _explicit_full++;
 138 }
 139 
 140 void ShenandoahCollectorPolicy::record_alloc_failure_to_full() {
 141   _heuristics->record_allocation_failure_gc();
 142   _alloc_failure_full++;
 143 }
 144 
 145 void ShenandoahCollectorPolicy::record_alloc_failure_to_degenerated(ShenandoahHeap::ShenandoahDegenPoint point) {
 146   assert(point < ShenandoahHeap::_DEGENERATED_LIMIT, "sanity");
 147   _heuristics->record_allocation_failure_gc();
 148   _alloc_failure_degenerated++;
 149   _degen_points[point]++;
 150 }
 151 
 152 void ShenandoahCollectorPolicy::record_degenerated_upgrade_to_full() {
 153   _alloc_failure_degenerated_upgrade_to_full++;
 154 }
 155 
 156 void ShenandoahCollectorPolicy::record_success_concurrent() {
 157   _heuristics->record_success_concurrent();
 158   _success_concurrent_gcs++;
 159 }
 160 
 161 void ShenandoahCollectorPolicy::record_success_partial() {
 162   _success_partial_gcs++;
 163 }
 164 
 165 void ShenandoahCollectorPolicy::record_success_degenerated() {
 166   _heuristics->record_success_degenerated();
 167   _success_degenerated_gcs++;
 168 }
 169 
 170 void ShenandoahCollectorPolicy::record_success_full() {
 171   _heuristics->record_success_full();
 172   _success_full_gcs++;
 173 }
 174 
 175 bool ShenandoahCollectorPolicy::should_start_normal_gc() {
 176   return _heuristics->should_start_normal_gc();
 177 }
 178 
 179 bool ShenandoahCollectorPolicy::should_degenerate_cycle() {
 180   return _heuristics->should_degenerate_cycle();
 181 }
 182 
 183 bool ShenandoahCollectorPolicy::update_refs() {
 184   return _heuristics->update_refs();
 185 }
 186 
 187 bool ShenandoahCollectorPolicy::should_start_update_refs() {
 188   return _heuristics->should_start_update_refs();
 189 }
 190 
 191 void ShenandoahCollectorPolicy::record_peak_occupancy() {
 192   _heuristics->record_peak_occupancy();
 193 }
 194 
 195 void ShenandoahCollectorPolicy::choose_collection_set(ShenandoahCollectionSet* collection_set) {
 196   _heuristics->choose_collection_set(collection_set);
 197 }
 198 
 199 bool ShenandoahCollectorPolicy::should_process_references() {
 200   return _heuristics->should_process_references();
 201 }
 202 
 203 bool ShenandoahCollectorPolicy::should_unload_classes() {
 204   return _heuristics->should_unload_classes();
 205 }
 206 
 207 size_t ShenandoahCollectorPolicy::cycle_counter() const {
 208   return _cycle_counter;
 209 }
 210 
 211 void ShenandoahCollectorPolicy::record_phase_time(ShenandoahPhaseTimings::Phase phase, double secs) {
 212   _heuristics->record_phase_time(phase, secs);
 213 }
 214 
 215 void ShenandoahCollectorPolicy::record_cycle_start() {
 216   _cycle_counter++;
 217   _heuristics->record_cycle_start();
 218 }
 219 
 220 void ShenandoahCollectorPolicy::record_cycle_end() {
 221   _heuristics->record_cycle_end();
 222 }
 223 
 224 void ShenandoahCollectorPolicy::record_shutdown() {
 225   _in_shutdown.set();
 226 }
 227 
 228 bool ShenandoahCollectorPolicy::is_at_shutdown() {
 229   return _in_shutdown.is_set();
 230 }
 231 
 232 void ShenandoahCollectorPolicy::print_gc_stats(outputStream* out) const {
 233   out->print_cr("Under allocation pressure, concurrent cycles may cancel, and either continue cycle");
 234   out->print_cr("under stop-the-world pause or result in stop-the-world Full GC. Increase heap size,");
 235   out->print_cr("tune GC heuristics, set more aggressive pacing delay, or lower allocation rate");
 236   out->print_cr("to avoid Degenerated and Full GC cycles.");
 237   out->cr();
 238 
 239   out->print_cr(SIZE_FORMAT_W(5) " successful partial concurrent GCs", _success_partial_gcs);
 240   out->cr();
 241 
 242   out->print_cr(SIZE_FORMAT_W(5) " successful concurrent GCs",         _success_concurrent_gcs);
 243   out->print_cr("  " SIZE_FORMAT_W(5) " invoked explicitly",           _explicit_concurrent);
 244   out->cr();
 245 
 246   out->print_cr(SIZE_FORMAT_W(5) " Degenerated GCs",                   _success_degenerated_gcs);
 247   out->print_cr("  " SIZE_FORMAT_W(5) " caused by allocation failure", _alloc_failure_degenerated);
 248   for (int c = 0; c < ShenandoahHeap::_DEGENERATED_LIMIT; c++) {
 249     if (_degen_points[c] > 0) {
 250       const char* desc = ShenandoahHeap::degen_point_to_string((ShenandoahHeap::ShenandoahDegenPoint)c);
 251       out->print_cr("    " SIZE_FORMAT_W(5) " happened at %s",         _degen_points[c], desc);
 252     }
 253   }
 254   out->print_cr("  " SIZE_FORMAT_W(5) " upgraded to Full GC",          _alloc_failure_degenerated_upgrade_to_full);
 255   out->cr();
 256 
 257   out->print_cr(SIZE_FORMAT_W(5) " Full GCs",                          _success_full_gcs + _alloc_failure_degenerated_upgrade_to_full);
 258   out->print_cr("  " SIZE_FORMAT_W(5) " invoked explicitly",           _explicit_full);
 259   out->print_cr("  " SIZE_FORMAT_W(5) " caused by allocation failure", _alloc_failure_full);
 260   out->print_cr("  " SIZE_FORMAT_W(5) " upgraded from Degenerated GC", _alloc_failure_degenerated_upgrade_to_full);
 261 }