1 /*
   2  * Copyright (c) 2013, 2018, Red Hat, Inc. All rights reserved.
   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_interface/gcCause.hpp"
  26 #include "gc_implementation/shared/gcTimer.hpp"
  27 #include "gc_implementation/shenandoah/shenandoahCollectionSet.hpp"
  28 #include "gc_implementation/shenandoah/shenandoahCollectorPolicy.hpp"
  29 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
  30 #include "gc_implementation/shenandoah/shenandoahLogging.hpp"
  31 #include "gc_implementation/shenandoah/heuristics/shenandoahHeuristics.hpp"
  32 
  33 ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() :
  34   _success_concurrent_gcs(0),
  35   _success_degenerated_gcs(0),
  36   _success_full_gcs(0),
  37   _alloc_failure_degenerated(0),
  38   _alloc_failure_full(0),
  39   _alloc_failure_degenerated_upgrade_to_full(0),
  40   _explicit_concurrent(0),
  41   _explicit_full(0),
  42   _implicit_concurrent(0),
  43   _implicit_full(0),
  44   _cycle_counter(0) {
  45 
  46   Copy::zero_to_bytes(_degen_points, sizeof(size_t) * ShenandoahHeap::_DEGENERATED_LIMIT);
  47 
  48   ShenandoahHeapRegion::setup_sizes(max_heap_byte_size());
  49 
  50   initialize_all();
  51 
  52   _tracer = new (ResourceObj::C_HEAP, mtGC) ShenandoahTracer();
  53 }
  54 
  55 BarrierSet::Name ShenandoahCollectorPolicy::barrier_set_name() {
  56   return BarrierSet::ShenandoahBarrierSet;
  57 }
  58 
  59 HeapWord* ShenandoahCollectorPolicy::mem_allocate_work(size_t size,
  60                                                        bool is_tlab,
  61                                                        bool* gc_overhead_limit_was_exceeded) {
  62   guarantee(false, "Not using this policy feature yet.");
  63   return NULL;
  64 }
  65 
  66 HeapWord* ShenandoahCollectorPolicy::satisfy_failed_allocation(size_t size, bool is_tlab) {
  67   guarantee(false, "Not using this policy feature yet.");
  68   return NULL;
  69 }
  70 
  71 MetaWord* ShenandoahCollectorPolicy::satisfy_failed_metadata_allocation(ClassLoaderData *loader_data,
  72                                                                         size_t size,
  73                                                                         Metaspace::MetadataType mdtype) {
  74   MetaWord* result;
  75 
  76   ShenandoahHeap* sh = ShenandoahHeap::heap();
  77 
  78   // Inform metaspace OOM to GC heuristics if class unloading is possible.
  79   ShenandoahHeuristics* h = sh->heuristics();
  80   if (h->can_unload_classes()) {
  81     h->record_metaspace_oom();
  82   }
  83 
  84   // Expand and retry allocation
  85   result = loader_data->metaspace_non_null()->expand_and_allocate(size, mdtype);
  86   if (result != NULL) {
  87     return result;
  88   }
  89 
  90   // Start full GC
  91   sh->collect(GCCause::_shenandoah_metadata_gc_clear_softrefs);
  92 
  93   // Retry allocation
  94   result = loader_data->metaspace_non_null()->allocate(size, mdtype);
  95   if (result != NULL) {
  96     return result;
  97   }
  98 
  99   // Expand and retry allocation
 100   result = loader_data->metaspace_non_null()->expand_and_allocate(size, mdtype);
 101   if (result != NULL) {
 102     return result;
 103   }
 104 
 105   // Out of memory
 106   return NULL;
 107 }
 108 
 109 void ShenandoahCollectorPolicy::initialize_alignments() {
 110   // This is expected by our algorithm for ShenandoahHeap::heap_region_containing().
 111   size_t align = ShenandoahHeapRegion::region_size_bytes();
 112   if (UseLargePages) {
 113     align = MAX2(align, os::large_page_size());
 114   }
 115   _space_alignment = align;
 116   _heap_alignment = align;
 117 }
 118 
 119 void ShenandoahCollectorPolicy::record_explicit_to_concurrent() {
 120   _explicit_concurrent++;
 121 }
 122 
 123 void ShenandoahCollectorPolicy::record_explicit_to_full() {
 124   _explicit_full++;
 125 }
 126 
 127 void ShenandoahCollectorPolicy::record_implicit_to_concurrent() {
 128   _implicit_concurrent++;
 129 }
 130 
 131 void ShenandoahCollectorPolicy::record_implicit_to_full() {
 132   _implicit_full++;
 133 }
 134 
 135 void ShenandoahCollectorPolicy::record_alloc_failure_to_full() {
 136   _alloc_failure_full++;
 137 }
 138 
 139 void ShenandoahCollectorPolicy::record_alloc_failure_to_degenerated(ShenandoahHeap::ShenandoahDegenPoint point) {
 140   assert(point < ShenandoahHeap::_DEGENERATED_LIMIT, "sanity");
 141   _alloc_failure_degenerated++;
 142   _degen_points[point]++;
 143 }
 144 
 145 void ShenandoahCollectorPolicy::record_degenerated_upgrade_to_full() {
 146   _alloc_failure_degenerated_upgrade_to_full++;
 147 }
 148 
 149 void ShenandoahCollectorPolicy::record_success_concurrent() {
 150   _success_concurrent_gcs++;
 151 }
 152 
 153 void ShenandoahCollectorPolicy::record_success_degenerated() {
 154   _success_degenerated_gcs++;
 155 }
 156 
 157 void ShenandoahCollectorPolicy::record_success_full() {
 158   _success_full_gcs++;
 159 }
 160 
 161 size_t ShenandoahCollectorPolicy::cycle_counter() const {
 162   return _cycle_counter;
 163 }
 164 
 165 void ShenandoahCollectorPolicy::record_cycle_start() {
 166   _cycle_counter++;
 167 }
 168 
 169 void ShenandoahCollectorPolicy::record_shutdown() {
 170   _in_shutdown.set();
 171 }
 172 
 173 bool ShenandoahCollectorPolicy::is_at_shutdown() {
 174   return _in_shutdown.is_set();
 175 }
 176 
 177 void ShenandoahCollectorPolicy::print_gc_stats(outputStream* out) const {
 178   out->print_cr("Under allocation pressure, concurrent cycles may cancel, and either continue cycle");
 179   out->print_cr("under stop-the-world pause or result in stop-the-world Full GC. Increase heap size,");
 180   out->print_cr("tune GC heuristics, set more aggressive pacing delay, or lower allocation rate");
 181   out->print_cr("to avoid Degenerated and Full GC cycles.");
 182   out->cr();
 183 
 184   out->print_cr(SIZE_FORMAT_W(5) " successful concurrent GCs",         _success_concurrent_gcs);
 185   out->print_cr("  " SIZE_FORMAT_W(5) " invoked explicitly",           _explicit_concurrent);
 186   out->print_cr("  " SIZE_FORMAT_W(5) " invoked implicitly",           _implicit_concurrent);
 187   out->cr();
 188 
 189   out->print_cr(SIZE_FORMAT_W(5) " Degenerated GCs",                   _success_degenerated_gcs);
 190   out->print_cr("  " SIZE_FORMAT_W(5) " caused by allocation failure", _alloc_failure_degenerated);
 191   for (int c = 0; c < ShenandoahHeap::_DEGENERATED_LIMIT; c++) {
 192     if (_degen_points[c] > 0) {
 193       const char* desc = ShenandoahHeap::degen_point_to_string((ShenandoahHeap::ShenandoahDegenPoint)c);
 194       out->print_cr("    " SIZE_FORMAT_W(5) " happened at %s",         _degen_points[c], desc);
 195     }
 196   }
 197   out->print_cr("  " SIZE_FORMAT_W(5) " upgraded to Full GC",          _alloc_failure_degenerated_upgrade_to_full);
 198   out->cr();
 199 
 200   out->print_cr(SIZE_FORMAT_W(5) " Full GCs",                          _success_full_gcs + _alloc_failure_degenerated_upgrade_to_full);
 201   out->print_cr("  " SIZE_FORMAT_W(5) " invoked explicitly",           _explicit_full);
 202   out->print_cr("  " SIZE_FORMAT_W(5) " invoked implicitly",           _implicit_full);
 203   out->print_cr("  " SIZE_FORMAT_W(5) " caused by allocation failure", _alloc_failure_full);
 204   out->print_cr("  " SIZE_FORMAT_W(5) " upgraded from Degenerated GC", _alloc_failure_degenerated_upgrade_to_full);
 205 }