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