1 /*
   2  * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "gc/shared/gcConfig.hpp"
  27 #include "runtime/globals_extension.hpp"
  28 #include "runtime/java.hpp"
  29 #include "runtime/os.hpp"
  30 #include "utilities/macros.hpp"
  31 #if INCLUDE_EPSILONGC
  32 #include "gc/epsilon/epsilonArguments.hpp"
  33 #endif
  34 #if INCLUDE_G1GC
  35 #include "gc/g1/g1Arguments.hpp"
  36 #endif
  37 #if INCLUDE_PARALLELGC
  38 #include "gc/parallel/parallelArguments.hpp"
  39 #endif
  40 #if INCLUDE_SERIALGC
  41 #include "gc/serial/serialArguments.hpp"
  42 #endif
  43 #if INCLUDE_SHENANDOAHGC
  44 #include "gc/shenandoah/shenandoahArguments.hpp"
  45 #endif
  46 #if INCLUDE_ZGC
  47 #include "gc/z/zArguments.hpp"
  48 #endif
  49 
  50 struct IncludedGC {
  51   bool&               _flag;
  52   CollectedHeap::Name _name;
  53   GCArguments&        _arguments;
  54   const char*         _hs_err_name;
  55 
  56   IncludedGC(bool& flag, CollectedHeap::Name name, GCArguments& arguments, const char* hs_err_name) :
  57       _flag(flag), _name(name), _arguments(arguments), _hs_err_name(hs_err_name) {}
  58 };
  59 
  60    EPSILONGC_ONLY(static EpsilonArguments    epsilonArguments;)
  61         G1GC_ONLY(static G1Arguments         g1Arguments;)
  62   PARALLELGC_ONLY(static ParallelArguments   parallelArguments;)
  63     SERIALGC_ONLY(static SerialArguments     serialArguments;)
  64 SHENANDOAHGC_ONLY(static ShenandoahArguments shenandoahArguments;)
  65          ZGC_ONLY(static ZArguments          zArguments;)
  66 
  67 // Table of included GCs, for translating between command
  68 // line flag, CollectedHeap::Name and GCArguments instance.
  69 static const IncludedGC IncludedGCs[] = {
  70    EPSILONGC_ONLY_ARG(IncludedGC(UseEpsilonGC,       CollectedHeap::Epsilon,    epsilonArguments,    "epsilon gc"))
  71         G1GC_ONLY_ARG(IncludedGC(UseG1GC,            CollectedHeap::G1,         g1Arguments,         "g1 gc"))
  72   PARALLELGC_ONLY_ARG(IncludedGC(UseParallelGC,      CollectedHeap::Parallel,   parallelArguments,   "parallel gc"))
  73     SERIALGC_ONLY_ARG(IncludedGC(UseSerialGC,        CollectedHeap::Serial,     serialArguments,     "serial gc"))
  74 SHENANDOAHGC_ONLY_ARG(IncludedGC(UseShenandoahGC,    CollectedHeap::Shenandoah, shenandoahArguments, "shenandoah gc"))
  75          ZGC_ONLY_ARG(IncludedGC(UseZGC,             CollectedHeap::Z,          zArguments,          "z gc"))
  76 };
  77 
  78 #define FOR_EACH_INCLUDED_GC(var)                                            \
  79   for (const IncludedGC* var = &IncludedGCs[0]; var < &IncludedGCs[ARRAY_SIZE(IncludedGCs)]; var++)
  80 
  81 #define FAIL_IF_SELECTED(option, enabled)                                   \
  82   if (option == enabled && FLAG_IS_CMDLINE(option)) {                       \
  83     vm_exit_during_initialization(enabled ?                                 \
  84                                   "Option -XX:+" #option " not supported" : \
  85                                   "Option -XX:-" #option " not supported"); \
  86   }
  87 
  88 GCArguments* GCConfig::_arguments = NULL;
  89 bool GCConfig::_gc_selected_ergonomically = false;
  90 
  91 void GCConfig::fail_if_non_included_gc_is_selected() {
  92   NOT_EPSILONGC(   FAIL_IF_SELECTED(UseEpsilonGC,       true));
  93   NOT_G1GC(        FAIL_IF_SELECTED(UseG1GC,            true));
  94   NOT_PARALLELGC(  FAIL_IF_SELECTED(UseParallelGC,      true));
  95   NOT_SERIALGC(    FAIL_IF_SELECTED(UseSerialGC,        true));
  96   NOT_SHENANDOAHGC(FAIL_IF_SELECTED(UseShenandoahGC,    true));
  97   NOT_ZGC(         FAIL_IF_SELECTED(UseZGC,             true));
  98 }
  99 
 100 void GCConfig::select_gc_ergonomically() {
 101   if (os::is_server_class_machine()) {
 102 #if INCLUDE_G1GC
 103     FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true);
 104 #elif INCLUDE_PARALLELGC
 105     FLAG_SET_ERGO_IF_DEFAULT(UseParallelGC, true);
 106 #elif INCLUDE_SERIALGC
 107     FLAG_SET_ERGO_IF_DEFAULT(UseSerialGC, true);
 108 #endif
 109   } else {
 110 #if INCLUDE_SERIALGC
 111     FLAG_SET_ERGO_IF_DEFAULT(UseSerialGC, true);
 112 #endif
 113   }
 114 }
 115 
 116 bool GCConfig::is_no_gc_selected() {
 117   FOR_EACH_INCLUDED_GC(gc) {
 118     if (gc->_flag) {
 119       return false;
 120     }
 121   }
 122 
 123   return true;
 124 }
 125 
 126 bool GCConfig::is_exactly_one_gc_selected() {
 127   CollectedHeap::Name selected = CollectedHeap::None;
 128 
 129   FOR_EACH_INCLUDED_GC(gc) {
 130     if (gc->_flag) {
 131       if (gc->_name == selected || selected == CollectedHeap::None) {
 132         // Selected
 133         selected = gc->_name;
 134       } else {
 135         // More than one selected
 136         return false;
 137       }
 138     }
 139   }
 140 
 141   return selected != CollectedHeap::None;
 142 }
 143 
 144 GCArguments* GCConfig::select_gc() {
 145   // Fail immediately if an unsupported GC is selected
 146   fail_if_non_included_gc_is_selected();
 147 
 148   if (is_no_gc_selected()) {
 149     // Try select GC ergonomically
 150     select_gc_ergonomically();
 151 
 152     if (is_no_gc_selected()) {
 153       // Failed to select GC ergonomically
 154       vm_exit_during_initialization("Garbage collector not selected "
 155                                     "(default collector explicitly disabled)", NULL);
 156     }
 157 
 158     // Succeeded to select GC ergonomically
 159     _gc_selected_ergonomically = true;
 160   }
 161 
 162   if (!is_exactly_one_gc_selected()) {
 163     // More than one GC selected
 164     vm_exit_during_initialization("Multiple garbage collectors selected", NULL);
 165   }
 166 
 167   // Exactly one GC selected
 168   FOR_EACH_INCLUDED_GC(gc) {
 169     if (gc->_flag) {
 170       return &gc->_arguments;
 171     }
 172   }
 173 
 174   fatal("Should have found the selected GC");
 175 
 176   return NULL;
 177 }
 178 
 179 void GCConfig::initialize() {
 180   assert(_arguments == NULL, "Already initialized");
 181   _arguments = select_gc();
 182 }
 183 
 184 bool GCConfig::is_gc_supported(CollectedHeap::Name name) {
 185   FOR_EACH_INCLUDED_GC(gc) {
 186     if (gc->_name == name && gc->_arguments.is_supported()) {
 187       // Supported
 188       return true;
 189     }
 190   }
 191 
 192   // Not supported
 193   return false;
 194 }
 195 
 196 bool GCConfig::is_gc_selected(CollectedHeap::Name name) {
 197   FOR_EACH_INCLUDED_GC(gc) {
 198     if (gc->_name == name && gc->_flag) {
 199       // Selected
 200       return true;
 201     }
 202   }
 203 
 204   // Not selected
 205   return false;
 206 }
 207 
 208 bool GCConfig::is_gc_selected_ergonomically() {
 209   return _gc_selected_ergonomically;
 210 }
 211 
 212 const char* GCConfig::hs_err_name() {
 213   if (is_exactly_one_gc_selected()) {
 214     // Exacly one GC selected
 215     FOR_EACH_INCLUDED_GC(gc) {
 216       if (gc->_flag) {
 217         return gc->_hs_err_name;
 218       }
 219     }
 220   }
 221 
 222   // Zero or more than one GC selected
 223   return "unknown gc";
 224 }
 225 
 226 const char* GCConfig::hs_err_name(CollectedHeap::Name name) {
 227   FOR_EACH_INCLUDED_GC(gc) {
 228     if (gc->_name == name) {
 229       return gc->_hs_err_name;
 230     }
 231   }
 232   return "unknown gc";
 233 }
 234 
 235 GCArguments* GCConfig::arguments() {
 236   assert(_arguments != NULL, "Not initialized");
 237   return _arguments;
 238 }