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/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_CMSGC
32#include "gc/cms/cmsArguments.hpp"
33#endif
34#if INCLUDE_EPSILONGC
35#include "gc/epsilon/epsilonArguments.hpp"
36#endif
37#if INCLUDE_G1GC
38#include "gc/g1/g1Arguments.hpp"
39#endif
40#if INCLUDE_PARALLELGC
41#include "gc/parallel/parallelArguments.hpp"
42#endif
43#if INCLUDE_SERIALGC
44#include "gc/serial/serialArguments.hpp"
45#endif
46#if INCLUDE_SHENANDOAHGC
47#include "gc/shenandoah/shenandoahArguments.hpp"
48#endif
49#if INCLUDE_ZGC
50#include "gc/z/zArguments.hpp"
51#endif
52
53struct SupportedGC {
54 bool& _flag;
55 CollectedHeap::Name _name;
56 GCArguments& _arguments;
57 const char* _hs_err_name;
58
59 SupportedGC(bool& flag, CollectedHeap::Name name, GCArguments& arguments, const char* hs_err_name) :
60 _flag(flag), _name(name), _arguments(arguments), _hs_err_name(hs_err_name) {}
61};
62
63 CMSGC_ONLY(static CMSArguments cmsArguments;)
64 EPSILONGC_ONLY(static EpsilonArguments epsilonArguments;)
65 G1GC_ONLY(static G1Arguments g1Arguments;)
66 PARALLELGC_ONLY(static ParallelArguments parallelArguments;)
67 SERIALGC_ONLY(static SerialArguments serialArguments;)
68SHENANDOAHGC_ONLY(static ShenandoahArguments shenandoahArguments;)
69 ZGC_ONLY(static ZArguments zArguments;)
70
71// Table of supported GCs, for translating between command
72// line flag, CollectedHeap::Name and GCArguments instance.
73static const SupportedGC SupportedGCs[] = {
74 CMSGC_ONLY_ARG(SupportedGC(UseConcMarkSweepGC, CollectedHeap::CMS, cmsArguments, "concurrent mark sweep gc"))
75 EPSILONGC_ONLY_ARG(SupportedGC(UseEpsilonGC, CollectedHeap::Epsilon, epsilonArguments, "epsilon gc"))
76 G1GC_ONLY_ARG(SupportedGC(UseG1GC, CollectedHeap::G1, g1Arguments, "g1 gc"))
77 PARALLELGC_ONLY_ARG(SupportedGC(UseParallelGC, CollectedHeap::Parallel, parallelArguments, "parallel gc"))
78 PARALLELGC_ONLY_ARG(SupportedGC(UseParallelOldGC, CollectedHeap::Parallel, parallelArguments, "parallel gc"))
79 SERIALGC_ONLY_ARG(SupportedGC(UseSerialGC, CollectedHeap::Serial, serialArguments, "serial gc"))
80SHENANDOAHGC_ONLY_ARG(SupportedGC(UseShenandoahGC, CollectedHeap::Shenandoah, shenandoahArguments, "shenandoah gc"))
81 ZGC_ONLY_ARG(SupportedGC(UseZGC, CollectedHeap::Z, zArguments, "z gc"))
82};
83
84#define FOR_EACH_SUPPORTED_GC(var) \
85 for (const SupportedGC* var = &SupportedGCs[0]; var < &SupportedGCs[ARRAY_SIZE(SupportedGCs)]; var++)
86
87#define FAIL_IF_SELECTED(option, enabled) \
88 if (option == enabled && FLAG_IS_CMDLINE(option)) { \
89 vm_exit_during_initialization(enabled ? \
90 "Option -XX:+" #option " not supported" : \
91 "Option -XX:-" #option " not supported"); \
92 }
93
94GCArguments* GCConfig::_arguments = NULL;
95bool GCConfig::_gc_selected_ergonomically = false;
96
97void GCConfig::fail_if_unsupported_gc_is_selected() {
98 NOT_CMSGC( FAIL_IF_SELECTED(UseConcMarkSweepGC, true));
99 NOT_EPSILONGC( FAIL_IF_SELECTED(UseEpsilonGC, true));
100 NOT_G1GC( FAIL_IF_SELECTED(UseG1GC, true));
101 NOT_PARALLELGC( FAIL_IF_SELECTED(UseParallelGC, true));
102 NOT_PARALLELGC( FAIL_IF_SELECTED(UseParallelOldGC, true));
103 NOT_SERIALGC( FAIL_IF_SELECTED(UseSerialGC, true));
104 NOT_SERIALGC( FAIL_IF_SELECTED(UseParallelOldGC, false));
105 NOT_SHENANDOAHGC(FAIL_IF_SELECTED(UseShenandoahGC, true));
106 NOT_ZGC( FAIL_IF_SELECTED(UseZGC, true));
107}
108
109void GCConfig::select_gc_ergonomically() {
110 if (os::is_server_class_machine()) {
111#if INCLUDE_G1GC
112 FLAG_SET_ERGO_IF_DEFAULT(UseG1GC, true);
113#elif INCLUDE_PARALLELGC
114 FLAG_SET_ERGO_IF_DEFAULT(UseParallelGC, true);
115#elif INCLUDE_SERIALGC
116 FLAG_SET_ERGO_IF_DEFAULT(UseSerialGC, true);
117#endif
118 } else {
119#if INCLUDE_SERIALGC
120 FLAG_SET_ERGO_IF_DEFAULT(UseSerialGC, true);
121#endif
122 }
123}
124
125bool GCConfig::is_no_gc_selected() {
126 FOR_EACH_SUPPORTED_GC(gc) {
127 if (gc->_flag) {
128 return false;
129 }
130 }
131
132 return true;
133}
134
135bool GCConfig::is_exactly_one_gc_selected() {
136 CollectedHeap::Name selected = CollectedHeap::None;
137
138 FOR_EACH_SUPPORTED_GC(gc) {
139 if (gc->_flag) {
140 if (gc->_name == selected || selected == CollectedHeap::None) {
141 // Selected
142 selected = gc->_name;
143 } else {
144 // More than one selected
145 return false;
146 }
147 }
148 }
149
150 return selected != CollectedHeap::None;
151}
152
153GCArguments* GCConfig::select_gc() {
154 // Fail immediately if an unsupported GC is selected
155 fail_if_unsupported_gc_is_selected();
156
157 if (is_no_gc_selected()) {
158 // Try select GC ergonomically
159 select_gc_ergonomically();
160
161 if (is_no_gc_selected()) {
162 // Failed to select GC ergonomically
163 vm_exit_during_initialization("Garbage collector not selected "
164 "(default collector explicitly disabled)", NULL);
165 }
166
167 // Succeeded to select GC ergonomically
168 _gc_selected_ergonomically = true;
169 }
170
171 if (!is_exactly_one_gc_selected()) {
172 // More than one GC selected
173 vm_exit_during_initialization("Multiple garbage collectors selected", NULL);
174 }
175
176 // Exactly one GC selected
177 FOR_EACH_SUPPORTED_GC(gc) {
178 if (gc->_flag) {
179 return &gc->_arguments;
180 }
181 }
182
183 fatal("Should have found the selected GC");
184
185 return NULL;
186}
187
188void GCConfig::initialize() {
189 assert(_arguments == NULL, "Already initialized");
190 _arguments = select_gc();
191}
192
193bool GCConfig::is_gc_supported(CollectedHeap::Name name) {
194 FOR_EACH_SUPPORTED_GC(gc) {
195 if (gc->_name == name) {
196 // Supported
197 return true;
198 }
199 }
200
201 // Not supported
202 return false;
203}
204
205bool GCConfig::is_gc_selected(CollectedHeap::Name name) {
206 FOR_EACH_SUPPORTED_GC(gc) {
207 if (gc->_name == name && gc->_flag) {
208 // Selected
209 return true;
210 }
211 }
212
213 // Not selected
214 return false;
215}
216
217bool GCConfig::is_gc_selected_ergonomically() {
218 return _gc_selected_ergonomically;
219}
220
221const char* GCConfig::hs_err_name() {
222 if (is_exactly_one_gc_selected()) {
223 // Exacly one GC selected
224 FOR_EACH_SUPPORTED_GC(gc) {
225 if (gc->_flag) {
226 return gc->_hs_err_name;
227 }
228 }
229 }
230
231 // Zero or more than one GC selected
232 return "unknown gc";
233}
234
235const char* GCConfig::hs_err_name(CollectedHeap::Name name) {
236 FOR_EACH_SUPPORTED_GC(gc) {
237 if (gc->_name == name) {
238 return gc->_hs_err_name;
239 }
240 }
241 return "unknown gc";
242}
243
244GCArguments* GCConfig::arguments() {
245 assert(_arguments != NULL, "Not initialized");
246 return _arguments;
247}
248