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