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.
  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.
  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 
  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 
  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 
 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 
 119 JVMFlag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose) {
 120   return MinMaxPLABSizeBounds("YoungPLABSize", value, verbose);
 121 }
 122 
 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 
 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 
 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 
 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 
 170 JVMFlag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose) {
 171   return CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(MaxHeapSize, value, verbose);
 172 }
 173 
 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 
 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 
 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 
 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 
 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 
 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 
 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)'.
 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 
 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 
 294 JVMFlag::Error MinHeapSizeConstraintFunc(size_t value, bool verbose) {
 295   return MaxSizeForHeapAlignment("MinHeapSize", value, verbose);
 296 }
 297 
 298 JVMFlag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose) {
 299   return MaxSizeForHeapAlignment("InitialHeapSize", value, verbose);
 300 }
 301 
 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 
 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 
 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 
 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 
 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 
 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.
 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 
 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 
 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 
 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 JVMFlag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose) {
 442   if (value != 0) {
 443     if (!is_power_of_2(value)) {
 444       JVMFlag::printError(verbose,
 445                           "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be "
 446                           "power of 2\n",
 447                           value);
 448       return JVMFlag::VIOLATES_CONSTRAINT;
 449     }
 450     if (value < ObjectAlignmentInBytes) {
 451       JVMFlag::printError(verbose,
 452                           "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be "
 453                           "greater than or equal to ObjectAlignmentInBytes (" INTX_FORMAT ")\n",
 454                           value, ObjectAlignmentInBytes);
 455       return JVMFlag::VIOLATES_CONSTRAINT;
 456     }
 457   }
 458   return JVMFlag::SUCCESS;
 459 }