1 /*
   2  * Copyright (c) 2018, 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/serial/serialArguments.hpp"
  27 #include "gc/shared/gcConfig.hpp"
  28 #include "runtime/java.hpp"
  29 #include "runtime/os.hpp"
  30 #include "utilities/macros.hpp"
  31 #if INCLUDE_ALL_GCS
  32 #include "gc/parallel/parallelArguments.hpp"
  33 #include "gc/cms/cmsArguments.hpp"
  34 #include "gc/g1/g1Arguments.hpp"
  35 #endif // INCLUDE_ALL_GCS
  36 
  37 struct SupportedGC {
  38   bool&               _flag;
  39   CollectedHeap::Name _name;
  40   GCArguments&        _arguments;
  41 
  42   SupportedGC(bool& flag, CollectedHeap::Name name, GCArguments& arguments) :
  43       _flag(flag), _name(name), _arguments(arguments) {}
  44 };
  45 
  46 static SerialArguments   serialArguments;
  47 #if INCLUDE_ALL_GCS
  48 static ParallelArguments parallelArguments;
  49 static CMSArguments      cmsArguments;
  50 static G1Arguments       g1Arguments;
  51 #endif // INCLUDE_ALL_GCS
  52 
  53 // Table of supported GCs, for translating between command
  54 // line flag, CollectedHeap::Name and GCArguments instance.
  55 static const SupportedGC SupportedGCs[] = {
  56   SupportedGC(UseSerialGC,        CollectedHeap::Serial,   serialArguments),
  57 #if INCLUDE_ALL_GCS
  58   SupportedGC(UseParallelGC,      CollectedHeap::Parallel, parallelArguments),
  59   SupportedGC(UseParallelOldGC,   CollectedHeap::Parallel, parallelArguments),
  60   SupportedGC(UseConcMarkSweepGC, CollectedHeap::CMS,      cmsArguments),
  61   SupportedGC(UseG1GC,            CollectedHeap::G1,       g1Arguments),
  62 #endif // INCLUDE_ALL_GCS
  63 };
  64 
  65 GCArguments* GCConfig::_arguments = NULL;
  66 bool GCConfig::_gc_selected_ergonomically = false;
  67 
  68 void GCConfig::select_gc_ergonomically() {
  69 #if INCLUDE_ALL_GCS
  70   if (os::is_server_class_machine()) {
  71     FLAG_SET_ERGO_IF_DEFAULT(bool, UseG1GC, true);
  72   } else {
  73     FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
  74   }
  75 #else
  76   UNSUPPORTED_OPTION(UseG1GC);
  77   UNSUPPORTED_OPTION(UseParallelGC);
  78   UNSUPPORTED_OPTION(UseParallelOldGC);
  79   UNSUPPORTED_OPTION(UseConcMarkSweepGC);
  80   FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
  81 #endif // INCLUDE_ALL_GCS
  82 }
  83 
  84 bool GCConfig::is_no_gc_selected() {
  85   for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
  86     if (SupportedGCs[i]._flag) {
  87       return false;
  88     }
  89   }
  90 
  91   return true;
  92 }
  93 
  94 bool GCConfig::is_exactly_one_gc_selected() {
  95   CollectedHeap::Name selected = CollectedHeap::None;
  96 
  97   for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
  98     if (SupportedGCs[i]._flag) {
  99       if (SupportedGCs[i]._name == selected || selected == CollectedHeap::None) {
 100         // Selected
 101         selected = SupportedGCs[i]._name;
 102       } else {
 103         // More than one selected
 104         return false;
 105       }
 106     }
 107   }
 108 
 109   return selected != CollectedHeap::None;
 110 }
 111 
 112 GCArguments* GCConfig::select_gc() {
 113   if (is_no_gc_selected()) {
 114     // Try select GC ergonomically
 115     select_gc_ergonomically();
 116 
 117     if (is_no_gc_selected()) {
 118       // Failed to select GC ergonomically
 119       vm_exit_during_initialization("Garbage collector not selected "
 120                                     "(default collector explicitly disabled)", NULL);
 121     }
 122 
 123     // Succeeded to select GC ergonomically
 124     _gc_selected_ergonomically = true;
 125   }
 126 
 127   if (is_exactly_one_gc_selected()) {
 128     // Exacly one GC selected
 129     for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
 130       if (SupportedGCs[i]._flag) {
 131         return &SupportedGCs[i]._arguments;
 132       }
 133     }
 134   }
 135 
 136   // More than one GC selected
 137   vm_exit_during_initialization("Multiple garbage collectors selected", NULL);
 138 
 139   return NULL;
 140 }
 141 
 142 void GCConfig::initialize() {
 143   assert(_arguments == NULL, "Already initialized");
 144   _arguments = select_gc();
 145 }
 146 
 147 bool GCConfig::is_gc_supported(CollectedHeap::Name name) {
 148   for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
 149     if (SupportedGCs[i]._name == name) {
 150       // Supported
 151       return true;
 152     }
 153   }
 154 
 155   // Not supported
 156   return false;
 157 }
 158 
 159 bool GCConfig::is_gc_selected(CollectedHeap::Name name) {
 160   for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
 161     if (SupportedGCs[i]._name == name && SupportedGCs[i]._flag) {
 162       // Selected
 163       return true;
 164     }
 165   }
 166 
 167   // Not selected
 168   return false;
 169 }
 170 
 171 bool GCConfig::is_gc_selected_ergonomically() {
 172   return _gc_selected_ergonomically;
 173 }
 174 
 175 GCArguments* GCConfig::arguments() {
 176   assert(_arguments != NULL, "Not initialized");
 177   return _arguments;
 178 }