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