1 /*
2 * Copyright (c) 2015, 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/cardTableRS.hpp"
27 #include "gc/shared/collectedHeap.hpp"
28 #include "gc/shared/gcArguments.hpp"
29 #include "gc/shared/gcConfig.hpp"
30 #include "gc/shared/jvmFlagConstraintsGC.hpp"
31 #include "gc/shared/plab.hpp"
32 #include "gc/shared/threadLocalAllocBuffer.hpp"
33 #include "runtime/arguments.hpp"
34 #include "runtime/globals.hpp"
35 #include "runtime/globals_extension.hpp"
36 #include "runtime/thread.inline.hpp"
37 #include "utilities/align.hpp"
38 #include "utilities/macros.hpp"
39 #include "utilities/powerOfTwo.hpp"
40 #if INCLUDE_G1GC
41 #include "gc/g1/jvmFlagConstraintsG1.hpp"
42 #endif
43 #if INCLUDE_PARALLELGC
44 #include "gc/parallel/jvmFlagConstraintsParallel.hpp"
45 #endif
46
47 // Some flags that have default values that indicate that the
48 // JVM should automatically determine an appropriate value
49 // for that flag. In those cases it is only appropriate for the
50 // constraint checking to be done if the user has specified the
51 // value(s) of the flag(s) on the command line. In the constraint
52 // checking functions, FLAG_IS_CMDLINE() is used to check if
53 // the flag has been set by the user and so should be checked.
54
55 // As ParallelGCThreads differs among GC modes, we need constraint function.
ParallelGCThreadsConstraintFunc(uint value,bool verbose)56 JVMFlag::Error ParallelGCThreadsConstraintFunc(uint value, bool verbose) {
57 JVMFlag::Error status = JVMFlag::SUCCESS;
58
59 #if INCLUDE_PARALLELGC
60 status = ParallelGCThreadsConstraintFuncParallel(value, verbose);
61 if (status != JVMFlag::SUCCESS) {
62 return status;
63 }
64 #endif
65
66 return status;
67 }
68
69 // As ConcGCThreads should be smaller than ParallelGCThreads,
70 // we need constraint function.
ConcGCThreadsConstraintFunc(uint value,bool verbose)71 JVMFlag::Error ConcGCThreadsConstraintFunc(uint value, bool verbose) {
72 // G1 GC use ConcGCThreads.
73 if (GCConfig::is_gc_selected(CollectedHeap::G1) && (value > ParallelGCThreads)) {
74 JVMFlag::printError(verbose,
75 "ConcGCThreads (" UINT32_FORMAT ") must be "
76 "less than or equal to ParallelGCThreads (" UINT32_FORMAT ")\n",
77 value, ParallelGCThreads);
78 return JVMFlag::VIOLATES_CONSTRAINT;
79 }
80
81 return JVMFlag::SUCCESS;
82 }
83
MinPLABSizeBounds(const char * name,size_t value,bool verbose)84 static JVMFlag::Error MinPLABSizeBounds(const char* name, size_t value, bool verbose) {
85 if ((GCConfig::is_gc_selected(CollectedHeap::G1) || GCConfig::is_gc_selected(CollectedHeap::Parallel)) &&
86 (value < PLAB::min_size())) {
87 JVMFlag::printError(verbose,
88 "%s (" SIZE_FORMAT ") must be "
89 "greater than or equal to ergonomic PLAB minimum size (" SIZE_FORMAT ")\n",
90 name, value, PLAB::min_size());
91 return JVMFlag::VIOLATES_CONSTRAINT;
92 }
93
94 return JVMFlag::SUCCESS;
95 }
96
MaxPLABSizeBounds(const char * name,size_t value,bool verbose)97 JVMFlag::Error MaxPLABSizeBounds(const char* name, size_t value, bool verbose) {
98 if ((GCConfig::is_gc_selected(CollectedHeap::G1) ||
99 GCConfig::is_gc_selected(CollectedHeap::Parallel)) && (value > PLAB::max_size())) {
100 JVMFlag::printError(verbose,
101 "%s (" SIZE_FORMAT ") must be "
102 "less than or equal to ergonomic PLAB maximum size (" SIZE_FORMAT ")\n",
103 name, value, PLAB::max_size());
104 return JVMFlag::VIOLATES_CONSTRAINT;
105 }
106
107 return JVMFlag::SUCCESS;
108 }
109
MinMaxPLABSizeBounds(const char * name,size_t value,bool verbose)110 static JVMFlag::Error MinMaxPLABSizeBounds(const char* name, size_t value, bool verbose) {
111 JVMFlag::Error status = MinPLABSizeBounds(name, value, verbose);
112
113 if (status == JVMFlag::SUCCESS) {
114 return MaxPLABSizeBounds(name, value, verbose);
115 }
116 return status;
117 }
118
YoungPLABSizeConstraintFunc(size_t value,bool verbose)119 JVMFlag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose) {
120 return MinMaxPLABSizeBounds("YoungPLABSize", value, verbose);
121 }
122
OldPLABSizeConstraintFunc(size_t value,bool verbose)123 JVMFlag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose) {
124 JVMFlag::Error status = JVMFlag::SUCCESS;
125
126 {
127 status = MinMaxPLABSizeBounds("OldPLABSize", value, verbose);
128 }
129
130 return status;
131 }
132
MinHeapFreeRatioConstraintFunc(uintx value,bool verbose)133 JVMFlag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose) {
134 if (value > MaxHeapFreeRatio) {
135 JVMFlag::printError(verbose,
136 "MinHeapFreeRatio (" UINTX_FORMAT ") must be "
137 "less than or equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n",
138 value, MaxHeapFreeRatio);
139 return JVMFlag::VIOLATES_CONSTRAINT;
140 } else {
141 return JVMFlag::SUCCESS;
142 }
143 }
144
MaxHeapFreeRatioConstraintFunc(uintx value,bool verbose)145 JVMFlag::Error MaxHeapFreeRatioConstraintFunc(uintx value, bool verbose) {
146 if (value < MinHeapFreeRatio) {
147 JVMFlag::printError(verbose,
148 "MaxHeapFreeRatio (" UINTX_FORMAT ") must be "
149 "greater than or equal to MinHeapFreeRatio (" UINTX_FORMAT ")\n",
150 value, MinHeapFreeRatio);
151 return JVMFlag::VIOLATES_CONSTRAINT;
152 } else {
153 return JVMFlag::SUCCESS;
154 }
155 }
156
CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(size_t maxHeap,intx softRef,bool verbose)157 static JVMFlag::Error CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(size_t maxHeap, intx softRef, bool verbose) {
158 if ((softRef > 0) && ((maxHeap / M) > (max_uintx / softRef))) {
159 JVMFlag::printError(verbose,
160 "Desired lifetime of SoftReferences cannot be expressed correctly. "
161 "MaxHeapSize (" SIZE_FORMAT ") or SoftRefLRUPolicyMSPerMB "
162 "(" INTX_FORMAT ") is too large\n",
163 maxHeap, softRef);
164 return JVMFlag::VIOLATES_CONSTRAINT;
165 } else {
166 return JVMFlag::SUCCESS;
167 }
168 }
169
SoftRefLRUPolicyMSPerMBConstraintFunc(intx value,bool verbose)170 JVMFlag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose) {
171 return CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(MaxHeapSize, value, verbose);
172 }
173
MarkStackSizeConstraintFunc(size_t value,bool verbose)174 JVMFlag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose) {
175 // value == 0 is handled by the range constraint.
176 if (value > MarkStackSizeMax) {
177 JVMFlag::printError(verbose,
178 "MarkStackSize (" SIZE_FORMAT ") must be "
179 "less than or equal to MarkStackSizeMax (" SIZE_FORMAT ")\n",
180 value, MarkStackSizeMax);
181 return JVMFlag::VIOLATES_CONSTRAINT;
182 } else {
183 return JVMFlag::SUCCESS;
184 }
185 }
186
MinMetaspaceFreeRatioConstraintFunc(uintx value,bool verbose)187 JVMFlag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
188 if (value > MaxMetaspaceFreeRatio) {
189 JVMFlag::printError(verbose,
190 "MinMetaspaceFreeRatio (" UINTX_FORMAT ") must be "
191 "less than or equal to MaxMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
192 value, MaxMetaspaceFreeRatio);
193 return JVMFlag::VIOLATES_CONSTRAINT;
194 } else {
195 return JVMFlag::SUCCESS;
196 }
197 }
198
MaxMetaspaceFreeRatioConstraintFunc(uintx value,bool verbose)199 JVMFlag::Error MaxMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
200 if (value < MinMetaspaceFreeRatio) {
201 JVMFlag::printError(verbose,
202 "MaxMetaspaceFreeRatio (" UINTX_FORMAT ") must be "
203 "greater than or equal to MinMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
204 value, MinMetaspaceFreeRatio);
205 return JVMFlag::VIOLATES_CONSTRAINT;
206 } else {
207 return JVMFlag::SUCCESS;
208 }
209 }
210
InitialTenuringThresholdConstraintFunc(uintx value,bool verbose)211 JVMFlag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose) {
212 #if INCLUDE_PARALLELGC
213 JVMFlag::Error status = InitialTenuringThresholdConstraintFuncParallel(value, verbose);
214 if (status != JVMFlag::SUCCESS) {
215 return status;
216 }
217 #endif
218
219 return JVMFlag::SUCCESS;
220 }
221
MaxTenuringThresholdConstraintFunc(uintx value,bool verbose)222 JVMFlag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose) {
223 #if INCLUDE_PARALLELGC
224 JVMFlag::Error status = MaxTenuringThresholdConstraintFuncParallel(value, verbose);
225 if (status != JVMFlag::SUCCESS) {
226 return status;
227 }
228 #endif
229
230 // MaxTenuringThreshold=0 means NeverTenure=false && AlwaysTenure=true
231 if ((value == 0) && (NeverTenure || !AlwaysTenure)) {
232 JVMFlag::printError(verbose,
233 "MaxTenuringThreshold (0) should match to NeverTenure=false "
234 "&& AlwaysTenure=true. But we have NeverTenure=%s "
235 "AlwaysTenure=%s\n",
236 NeverTenure ? "true" : "false",
237 AlwaysTenure ? "true" : "false");
238 return JVMFlag::VIOLATES_CONSTRAINT;
239 }
240 return JVMFlag::SUCCESS;
241 }
242
MaxGCPauseMillisConstraintFunc(uintx value,bool verbose)243 JVMFlag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose) {
244 #if INCLUDE_G1GC
245 JVMFlag::Error status = MaxGCPauseMillisConstraintFuncG1(value, verbose);
246 if (status != JVMFlag::SUCCESS) {
247 return status;
248 }
249 #endif
250
251 return JVMFlag::SUCCESS;
252 }
253
GCPauseIntervalMillisConstraintFunc(uintx value,bool verbose)254 JVMFlag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose) {
255 #if INCLUDE_G1GC
256 JVMFlag::Error status = GCPauseIntervalMillisConstraintFuncG1(value, verbose);
257 if (status != JVMFlag::SUCCESS) {
258 return status;
259 }
260 #endif
261
262 return JVMFlag::SUCCESS;
263 }
264
265 // To avoid an overflow by 'align_up(value, alignment)'.
MaxSizeForAlignment(const char * name,size_t value,size_t alignment,bool verbose)266 static JVMFlag::Error MaxSizeForAlignment(const char* name, size_t value, size_t alignment, bool verbose) {
267 size_t aligned_max = ((max_uintx - alignment) & ~(alignment-1));
268 if (value > aligned_max) {
269 JVMFlag::printError(verbose,
270 "%s (" SIZE_FORMAT ") must be "
271 "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
272 name, value, aligned_max);
273 return JVMFlag::VIOLATES_CONSTRAINT;
274 }
275 return JVMFlag::SUCCESS;
276 }
277
MaxSizeForHeapAlignment(const char * name,size_t value,bool verbose)278 static JVMFlag::Error MaxSizeForHeapAlignment(const char* name, size_t value, bool verbose) {
279 size_t heap_alignment;
280
281 #if INCLUDE_G1GC
282 if (UseG1GC) {
283 // For G1 GC, we don't know until G1CollectedHeap is created.
284 heap_alignment = MaxSizeForHeapAlignmentG1();
285 } else
286 #endif
287 {
288 heap_alignment = GCArguments::compute_heap_alignment();
289 }
290
291 return MaxSizeForAlignment(name, value, heap_alignment, verbose);
292 }
293
MinHeapSizeConstraintFunc(size_t value,bool verbose)294 JVMFlag::Error MinHeapSizeConstraintFunc(size_t value, bool verbose) {
295 return MaxSizeForHeapAlignment("MinHeapSize", value, verbose);
296 }
297
InitialHeapSizeConstraintFunc(size_t value,bool verbose)298 JVMFlag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose) {
299 return MaxSizeForHeapAlignment("InitialHeapSize", value, verbose);
300 }
301
MaxHeapSizeConstraintFunc(size_t value,bool verbose)302 JVMFlag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose) {
303 JVMFlag::Error status = MaxSizeForHeapAlignment("MaxHeapSize", value, verbose);
304
305 if (status == JVMFlag::SUCCESS) {
306 status = CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(value, SoftRefLRUPolicyMSPerMB, verbose);
307 }
308 return status;
309 }
310
SoftMaxHeapSizeConstraintFunc(size_t value,bool verbose)311 JVMFlag::Error SoftMaxHeapSizeConstraintFunc(size_t value, bool verbose) {
312 if (value > MaxHeapSize) {
313 JVMFlag::printError(verbose, "SoftMaxHeapSize must be less than or equal to the maximum heap size\n");
314 return JVMFlag::VIOLATES_CONSTRAINT;
315 }
316
317 return JVMFlag::SUCCESS;
318 }
319
HeapBaseMinAddressConstraintFunc(size_t value,bool verbose)320 JVMFlag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose) {
321 // If an overflow happened in Arguments::set_heap_size(), MaxHeapSize will have too large a value.
322 // Check for this by ensuring that MaxHeapSize plus the requested min base address still fit within max_uintx.
323 if (UseCompressedOops && FLAG_IS_ERGO(MaxHeapSize) && (value > (max_uintx - MaxHeapSize))) {
324 JVMFlag::printError(verbose,
325 "HeapBaseMinAddress (" SIZE_FORMAT ") or MaxHeapSize (" SIZE_FORMAT ") is too large. "
326 "Sum of them must be less than or equal to maximum of size_t (" SIZE_FORMAT ")\n",
327 value, MaxHeapSize, max_uintx);
328 return JVMFlag::VIOLATES_CONSTRAINT;
329 }
330
331 return MaxSizeForHeapAlignment("HeapBaseMinAddress", value, verbose);
332 }
333
NewSizeConstraintFunc(size_t value,bool verbose)334 JVMFlag::Error NewSizeConstraintFunc(size_t value, bool verbose) {
335 #if INCLUDE_G1GC
336 JVMFlag::Error status = NewSizeConstraintFuncG1(value, verbose);
337 if (status != JVMFlag::SUCCESS) {
338 return status;
339 }
340 #endif
341
342 return JVMFlag::SUCCESS;
343 }
344
MinTLABSizeConstraintFunc(size_t value,bool verbose)345 JVMFlag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose) {
346 // At least, alignment reserve area is needed.
347 if (value < ThreadLocalAllocBuffer::alignment_reserve_in_bytes()) {
348 JVMFlag::printError(verbose,
349 "MinTLABSize (" SIZE_FORMAT ") must be "
350 "greater than or equal to reserved area in TLAB (" SIZE_FORMAT ")\n",
351 value, ThreadLocalAllocBuffer::alignment_reserve_in_bytes());
352 return JVMFlag::VIOLATES_CONSTRAINT;
353 }
354 if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
355 JVMFlag::printError(verbose,
356 "MinTLABSize (" SIZE_FORMAT ") must be "
357 "less than or equal to ergonomic TLAB maximum (" SIZE_FORMAT ")\n",
358 value, ThreadLocalAllocBuffer::max_size() * HeapWordSize);
359 return JVMFlag::VIOLATES_CONSTRAINT;
360 }
361 return JVMFlag::SUCCESS;
362 }
363
TLABSizeConstraintFunc(size_t value,bool verbose)364 JVMFlag::Error TLABSizeConstraintFunc(size_t value, bool verbose) {
365 // Skip for default value of zero which means set ergonomically.
366 if (FLAG_IS_CMDLINE(TLABSize)) {
367 if (value < MinTLABSize) {
368 JVMFlag::printError(verbose,
369 "TLABSize (" SIZE_FORMAT ") must be "
370 "greater than or equal to MinTLABSize (" SIZE_FORMAT ")\n",
371 value, MinTLABSize);
372 return JVMFlag::VIOLATES_CONSTRAINT;
373 }
374 if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
375 JVMFlag::printError(verbose,
376 "TLABSize (" SIZE_FORMAT ") must be "
377 "less than or equal to ergonomic TLAB maximum size (" SIZE_FORMAT ")\n",
378 value, (ThreadLocalAllocBuffer::max_size() * HeapWordSize));
379 return JVMFlag::VIOLATES_CONSTRAINT;
380 }
381 }
382 return JVMFlag::SUCCESS;
383 }
384
385 // We will protect overflow from ThreadLocalAllocBuffer::record_slow_allocation(),
386 // so AfterMemoryInit type is enough to check.
TLABWasteIncrementConstraintFunc(uintx value,bool verbose)387 JVMFlag::Error TLABWasteIncrementConstraintFunc(uintx value, bool verbose) {
388 if (UseTLAB) {
389 size_t refill_waste_limit = Thread::current()->tlab().refill_waste_limit();
390
391 // Compare with 'max_uintx' as ThreadLocalAllocBuffer::_refill_waste_limit is 'size_t'.
392 if (refill_waste_limit > (max_uintx - value)) {
393 JVMFlag::printError(verbose,
394 "TLABWasteIncrement (" UINTX_FORMAT ") must be "
395 "less than or equal to ergonomic TLAB waste increment maximum size(" SIZE_FORMAT ")\n",
396 value, (max_uintx - refill_waste_limit));
397 return JVMFlag::VIOLATES_CONSTRAINT;
398 }
399 }
400 return JVMFlag::SUCCESS;
401 }
402
SurvivorRatioConstraintFunc(uintx value,bool verbose)403 JVMFlag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose) {
404 if (FLAG_IS_CMDLINE(SurvivorRatio) &&
405 (value > (MaxHeapSize / SpaceAlignment))) {
406 JVMFlag::printError(verbose,
407 "SurvivorRatio (" UINTX_FORMAT ") must be "
408 "less than or equal to ergonomic SurvivorRatio maximum (" SIZE_FORMAT ")\n",
409 value,
410 (MaxHeapSize / SpaceAlignment));
411 return JVMFlag::VIOLATES_CONSTRAINT;
412 } else {
413 return JVMFlag::SUCCESS;
414 }
415 }
416
MetaspaceSizeConstraintFunc(size_t value,bool verbose)417 JVMFlag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose) {
418 if (value > MaxMetaspaceSize) {
419 JVMFlag::printError(verbose,
420 "MetaspaceSize (" SIZE_FORMAT ") must be "
421 "less than or equal to MaxMetaspaceSize (" SIZE_FORMAT ")\n",
422 value, MaxMetaspaceSize);
423 return JVMFlag::VIOLATES_CONSTRAINT;
424 } else {
425 return JVMFlag::SUCCESS;
426 }
427 }
428
MaxMetaspaceSizeConstraintFunc(size_t value,bool verbose)429 JVMFlag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
430 if (value < MetaspaceSize) {
431 JVMFlag::printError(verbose,
432 "MaxMetaspaceSize (" SIZE_FORMAT ") must be "
433 "greater than or equal to MetaspaceSize (" SIZE_FORMAT ")\n",
434 value, MaxMetaspaceSize);
435 return JVMFlag::VIOLATES_CONSTRAINT;
436 } else {
437 return JVMFlag::SUCCESS;
438 }
439 }
440
441