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 #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
InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value,bool verbose)265 JVMFlag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
266 size_t aligned_max = align_down(max_uintx/2, Metaspace::reserve_alignment_words());
267 if (value > aligned_max) {
268 JVMFlag::printError(verbose,
269 "InitialBootClassLoaderMetaspaceSize (" SIZE_FORMAT ") must be "
270 "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
271 value, aligned_max);
272 return JVMFlag::VIOLATES_CONSTRAINT;
273 }
274 return JVMFlag::SUCCESS;
275 }
276
277 // To avoid an overflow by 'align_up(value, alignment)'.
MaxSizeForAlignment(const char * name,size_t value,size_t alignment,bool verbose)278 static JVMFlag::Error MaxSizeForAlignment(const char* name, size_t value, size_t alignment, bool verbose) {
279 size_t aligned_max = ((max_uintx - alignment) & ~(alignment-1));
280 if (value > aligned_max) {
281 JVMFlag::printError(verbose,
282 "%s (" SIZE_FORMAT ") must be "
283 "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
284 name, value, aligned_max);
285 return JVMFlag::VIOLATES_CONSTRAINT;
286 }
287 return JVMFlag::SUCCESS;
288 }
289
MaxSizeForHeapAlignment(const char * name,size_t value,bool verbose)290 static JVMFlag::Error MaxSizeForHeapAlignment(const char* name, size_t value, bool verbose) {
291 size_t heap_alignment;
292
293 #if INCLUDE_G1GC
294 if (UseG1GC) {
295 // For G1 GC, we don't know until G1CollectedHeap is created.
296 heap_alignment = MaxSizeForHeapAlignmentG1();
297 } else
298 #endif
299 {
300 heap_alignment = GCArguments::compute_heap_alignment();
301 }
302
303 return MaxSizeForAlignment(name, value, heap_alignment, verbose);
304 }
305
MinHeapSizeConstraintFunc(size_t value,bool verbose)306 JVMFlag::Error MinHeapSizeConstraintFunc(size_t value, bool verbose) {
307 return MaxSizeForHeapAlignment("MinHeapSize", value, verbose);
308 }
309
InitialHeapSizeConstraintFunc(size_t value,bool verbose)310 JVMFlag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose) {
311 return MaxSizeForHeapAlignment("InitialHeapSize", value, verbose);
312 }
313
MaxHeapSizeConstraintFunc(size_t value,bool verbose)314 JVMFlag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose) {
315 JVMFlag::Error status = MaxSizeForHeapAlignment("MaxHeapSize", value, verbose);
316
317 if (status == JVMFlag::SUCCESS) {
318 status = CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(value, SoftRefLRUPolicyMSPerMB, verbose);
319 }
320 return status;
321 }
322
SoftMaxHeapSizeConstraintFunc(size_t value,bool verbose)323 JVMFlag::Error SoftMaxHeapSizeConstraintFunc(size_t value, bool verbose) {
324 if (value > MaxHeapSize) {
325 JVMFlag::printError(verbose, "SoftMaxHeapSize must be less than or equal to the maximum heap size\n");
326 return JVMFlag::VIOLATES_CONSTRAINT;
327 }
328
329 return JVMFlag::SUCCESS;
330 }
331
HeapBaseMinAddressConstraintFunc(size_t value,bool verbose)332 JVMFlag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose) {
333 // If an overflow happened in Arguments::set_heap_size(), MaxHeapSize will have too large a value.
334 // Check for this by ensuring that MaxHeapSize plus the requested min base address still fit within max_uintx.
335 if (UseCompressedOops && FLAG_IS_ERGO(MaxHeapSize) && (value > (max_uintx - MaxHeapSize))) {
336 JVMFlag::printError(verbose,
337 "HeapBaseMinAddress (" SIZE_FORMAT ") or MaxHeapSize (" SIZE_FORMAT ") is too large. "
338 "Sum of them must be less than or equal to maximum of size_t (" SIZE_FORMAT ")\n",
339 value, MaxHeapSize, max_uintx);
340 return JVMFlag::VIOLATES_CONSTRAINT;
341 }
342
343 return MaxSizeForHeapAlignment("HeapBaseMinAddress", value, verbose);
344 }
345
NewSizeConstraintFunc(size_t value,bool verbose)346 JVMFlag::Error NewSizeConstraintFunc(size_t value, bool verbose) {
347 #if INCLUDE_G1GC
348 JVMFlag::Error status = NewSizeConstraintFuncG1(value, verbose);
349 if (status != JVMFlag::SUCCESS) {
350 return status;
351 }
352 #endif
353
354 return JVMFlag::SUCCESS;
355 }
356
MinTLABSizeConstraintFunc(size_t value,bool verbose)357 JVMFlag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose) {
358 // At least, alignment reserve area is needed.
359 if (value < ThreadLocalAllocBuffer::alignment_reserve_in_bytes()) {
360 JVMFlag::printError(verbose,
361 "MinTLABSize (" SIZE_FORMAT ") must be "
362 "greater than or equal to reserved area in TLAB (" SIZE_FORMAT ")\n",
363 value, ThreadLocalAllocBuffer::alignment_reserve_in_bytes());
364 return JVMFlag::VIOLATES_CONSTRAINT;
365 }
366 if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
367 JVMFlag::printError(verbose,
368 "MinTLABSize (" SIZE_FORMAT ") must be "
369 "less than or equal to ergonomic TLAB maximum (" SIZE_FORMAT ")\n",
370 value, ThreadLocalAllocBuffer::max_size() * HeapWordSize);
371 return JVMFlag::VIOLATES_CONSTRAINT;
372 }
373 return JVMFlag::SUCCESS;
374 }
375
TLABSizeConstraintFunc(size_t value,bool verbose)376 JVMFlag::Error TLABSizeConstraintFunc(size_t value, bool verbose) {
377 // Skip for default value of zero which means set ergonomically.
378 if (FLAG_IS_CMDLINE(TLABSize)) {
379 if (value < MinTLABSize) {
380 JVMFlag::printError(verbose,
381 "TLABSize (" SIZE_FORMAT ") must be "
382 "greater than or equal to MinTLABSize (" SIZE_FORMAT ")\n",
383 value, MinTLABSize);
384 return JVMFlag::VIOLATES_CONSTRAINT;
385 }
386 if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
387 JVMFlag::printError(verbose,
388 "TLABSize (" SIZE_FORMAT ") must be "
389 "less than or equal to ergonomic TLAB maximum size (" SIZE_FORMAT ")\n",
390 value, (ThreadLocalAllocBuffer::max_size() * HeapWordSize));
391 return JVMFlag::VIOLATES_CONSTRAINT;
392 }
393 }
394 return JVMFlag::SUCCESS;
395 }
396
397 // We will protect overflow from ThreadLocalAllocBuffer::record_slow_allocation(),
398 // so AfterMemoryInit type is enough to check.
TLABWasteIncrementConstraintFunc(uintx value,bool verbose)399 JVMFlag::Error TLABWasteIncrementConstraintFunc(uintx value, bool verbose) {
400 if (UseTLAB) {
401 size_t refill_waste_limit = Thread::current()->tlab().refill_waste_limit();
402
403 // Compare with 'max_uintx' as ThreadLocalAllocBuffer::_refill_waste_limit is 'size_t'.
404 if (refill_waste_limit > (max_uintx - value)) {
405 JVMFlag::printError(verbose,
406 "TLABWasteIncrement (" UINTX_FORMAT ") must be "
407 "less than or equal to ergonomic TLAB waste increment maximum size(" SIZE_FORMAT ")\n",
408 value, (max_uintx - refill_waste_limit));
409 return JVMFlag::VIOLATES_CONSTRAINT;
410 }
411 }
412 return JVMFlag::SUCCESS;
413 }
414
SurvivorRatioConstraintFunc(uintx value,bool verbose)415 JVMFlag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose) {
416 if (FLAG_IS_CMDLINE(SurvivorRatio) &&
417 (value > (MaxHeapSize / SpaceAlignment))) {
418 JVMFlag::printError(verbose,
419 "SurvivorRatio (" UINTX_FORMAT ") must be "
420 "less than or equal to ergonomic SurvivorRatio maximum (" SIZE_FORMAT ")\n",
421 value,
422 (MaxHeapSize / SpaceAlignment));
423 return JVMFlag::VIOLATES_CONSTRAINT;
424 } else {
425 return JVMFlag::SUCCESS;
426 }
427 }
428
MetaspaceSizeConstraintFunc(size_t value,bool verbose)429 JVMFlag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose) {
430 if (value > MaxMetaspaceSize) {
431 JVMFlag::printError(verbose,
432 "MetaspaceSize (" SIZE_FORMAT ") must be "
433 "less than or equal to MaxMetaspaceSize (" SIZE_FORMAT ")\n",
434 value, MaxMetaspaceSize);
435 return JVMFlag::VIOLATES_CONSTRAINT;
436 } else {
437 return JVMFlag::SUCCESS;
438 }
439 }
440
MaxMetaspaceSizeConstraintFunc(size_t value,bool verbose)441 JVMFlag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
442 if (value < MetaspaceSize) {
443 JVMFlag::printError(verbose,
444 "MaxMetaspaceSize (" SIZE_FORMAT ") must be "
445 "greater than or equal to MetaspaceSize (" SIZE_FORMAT ")\n",
446 value, MaxMetaspaceSize);
447 return JVMFlag::VIOLATES_CONSTRAINT;
448 } else {
449 return JVMFlag::SUCCESS;
450 }
451 }
452
SurvivorAlignmentInBytesConstraintFunc(intx value,bool verbose)453 JVMFlag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose) {
454 if (value != 0) {
455 if (!is_power_of_2(value)) {
456 JVMFlag::printError(verbose,
457 "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be "
458 "power of 2\n",
459 value);
460 return JVMFlag::VIOLATES_CONSTRAINT;
461 }
462 if (value < ObjectAlignmentInBytes) {
463 JVMFlag::printError(verbose,
464 "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be "
465 "greater than or equal to ObjectAlignmentInBytes (" INTX_FORMAT ")\n",
466 value, ObjectAlignmentInBytes);
467 return JVMFlag::VIOLATES_CONSTRAINT;
468 }
469 }
470 return JVMFlag::SUCCESS;
471 }
472