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