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