blob: 192cad86e67d38369970499cb48c65cf89dfc598 [file] [log] [blame]
/*
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "precompiled.hpp"
#include "gc/z/zAddressSpaceLimit.hpp"
#include "gc/z/zArguments.hpp"
#include "gc/z/zCollectedHeap.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zHeuristics.hpp"
#include "gc/shared/gcArguments.hpp"
#include "runtime/globals.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/java.hpp"
void ZArguments::initialize_alignments() {
SpaceAlignment = ZGranuleSize;
HeapAlignment = SpaceAlignment;
}
void ZArguments::initialize_heap_flags_and_sizes() {
if (!FLAG_IS_CMDLINE(MaxHeapSize) &&
!FLAG_IS_CMDLINE(MaxRAMFraction) &&
!FLAG_IS_CMDLINE(MaxRAMPercentage) &&
!FLAG_IS_CMDLINE(SoftMaxHeapSize)) {
// We are really just guessing how much memory the program needs.
// When that is the case, we don't want the soft and hard limits to be the same
// as it can cause flakyness in the number of GC threads used, in order to keep
// to a random number we just pulled out of thin air.
FLAG_SET_ERGO(SoftMaxHeapSize, MaxHeapSize * 90 / 100);
}
}
void ZArguments::select_max_gc_threads() {
// Select number of parallel threads
if (FLAG_IS_DEFAULT(ParallelGCThreads)) {
FLAG_SET_DEFAULT(ParallelGCThreads, ZHeuristics::nparallel_workers());
}
if (ParallelGCThreads == 0) {
vm_exit_during_initialization("The flag -XX:+UseZGC can not be combined with -XX:ParallelGCThreads=0");
}
// The max number of concurrent threads we heuristically want for a generation
uint max_nworkers_generation;
if (FLAG_IS_DEFAULT(ConcGCThreads)) {
max_nworkers_generation = ZHeuristics::nconcurrent_workers();
// Computed max number of GC threads at a time in the machine
uint max_nworkers = max_nworkers_generation;
if (!FLAG_IS_DEFAULT(ZYoungGCThreads)) {
max_nworkers = MAX2(max_nworkers, ZYoungGCThreads);
}
if (!FLAG_IS_DEFAULT(ZOldGCThreads)) {
max_nworkers = MAX2(max_nworkers, ZOldGCThreads);
}
FLAG_SET_DEFAULT(ConcGCThreads, max_nworkers);
} else {
max_nworkers_generation = ConcGCThreads;
}
if (FLAG_IS_DEFAULT(ZYoungGCThreads)) {
if (UseDynamicNumberOfGCThreads) {
FLAG_SET_ERGO(ZYoungGCThreads, max_nworkers_generation);
} else {
const uint static_young_threads = MAX2(uint(max_nworkers_generation * 0.9), 1u);
FLAG_SET_ERGO(ZYoungGCThreads, static_young_threads);
}
}
if (FLAG_IS_DEFAULT(ZOldGCThreads)) {
if (UseDynamicNumberOfGCThreads) {
FLAG_SET_ERGO(ZOldGCThreads, max_nworkers_generation);
} else {
const uint static_old_threads = MAX2(ConcGCThreads - ZYoungGCThreads, 1u);
FLAG_SET_ERGO(ZOldGCThreads, static_old_threads);
}
}
if (ConcGCThreads == 0) {
vm_exit_during_initialization("The flag -XX:+UseZGC can not be combined with -XX:ConcGCThreads=0");
}
if (ZYoungGCThreads > ConcGCThreads) {
vm_exit_during_initialization("The flag -XX:ZYoungGCThreads can't be higher than -XX:ConcGCThreads");
} else if (ZYoungGCThreads == 0) {
vm_exit_during_initialization("The flag -XX:ZYoungGCThreads can't be lower than 1");
}
if (ZOldGCThreads > ConcGCThreads) {
vm_exit_during_initialization("The flag -XX:ZOldGCThreads can't be higher than -XX:ConcGCThreads");
} else if (ZOldGCThreads == 0) {
vm_exit_during_initialization("The flag -XX:ZOldGCThreads can't be lower than 1");
}
}
void ZArguments::initialize() {
// Check mark stack size
const size_t mark_stack_space_limit = ZAddressSpaceLimit::mark_stack();
if (ZMarkStackSpaceLimit > mark_stack_space_limit) {
if (!FLAG_IS_DEFAULT(ZMarkStackSpaceLimit)) {
vm_exit_during_initialization("ZMarkStackSpaceLimit too large for limited address space");
}
FLAG_SET_DEFAULT(ZMarkStackSpaceLimit, mark_stack_space_limit);
}
// Enable NUMA by default
if (FLAG_IS_DEFAULT(UseNUMA)) {
FLAG_SET_DEFAULT(UseNUMA, true);
}
select_max_gc_threads();
// Backwards compatible alias for ZCollectionIntervalMajor
if (!FLAG_IS_DEFAULT(ZCollectionInterval)) {
FLAG_SET_ERGO_IF_DEFAULT(ZCollectionIntervalMajor, ZCollectionInterval);
}
if (FLAG_IS_DEFAULT(ZFragmentationLimit)) {
FLAG_SET_DEFAULT(ZFragmentationLimit, 5.0);
}
// Set medium page size here because MaxTenuringThreshold may use it.
ZHeuristics::set_medium_page_size();
if (!FLAG_IS_DEFAULT(ZTenuringThreshold) && ZTenuringThreshold != -1) {
FLAG_SET_ERGO_IF_DEFAULT(MaxTenuringThreshold, ZTenuringThreshold);
if (MaxTenuringThreshold == 0) {
FLAG_SET_ERGO_IF_DEFAULT(AlwaysTenure, true);
}
}
if (FLAG_IS_DEFAULT(MaxTenuringThreshold)) {
uint tenuring_threshold;
for (tenuring_threshold = 0; tenuring_threshold < MaxTenuringThreshold; ++tenuring_threshold) {
// Reduce the number of object ages, if the resulting garbage is too high
const size_t medium_page_overhead = ZPageSizeMedium * tenuring_threshold;
const size_t small_page_overhead = ZPageSizeSmall * ConcGCThreads * tenuring_threshold;
if (small_page_overhead + medium_page_overhead >= ZHeuristics::significant_young_overhead()) {
break;
}
}
FLAG_SET_DEFAULT(MaxTenuringThreshold, tenuring_threshold);
if (tenuring_threshold == 0 && FLAG_IS_DEFAULT(AlwaysTenure)) {
// Some flag constraint function says AlwaysTenure must be true iff MaxTenuringThreshold == 0
FLAG_SET_DEFAULT(AlwaysTenure, true);
}
}
if (!FLAG_IS_DEFAULT(ZTenuringThreshold) && NeverTenure) {
vm_exit_during_initialization(err_msg("ZTenuringThreshold and NeverTenure are incompatible"));
}
// Large page size must match granule size
if (!FLAG_IS_DEFAULT(LargePageSizeInBytes) && LargePageSizeInBytes != ZGranuleSize) {
vm_exit_during_initialization(err_msg("Incompatible -XX:LargePageSizeInBytes, only "
SIZE_FORMAT "M large pages are supported by ZGC",
ZGranuleSize / M));
}
if (!FLAG_IS_DEFAULT(ZTenuringThreshold) && ZTenuringThreshold > static_cast<int>(MaxTenuringThreshold)) {
vm_exit_during_initialization(err_msg("ZTenuringThreshold must be be within bounds of "
"MaxTenuringThreshold"));
}
#ifdef COMPILER2
// Enable loop strip mining by default
if (FLAG_IS_DEFAULT(UseCountedLoopSafepoints)) {
FLAG_SET_DEFAULT(UseCountedLoopSafepoints, true);
if (FLAG_IS_DEFAULT(LoopStripMiningIter)) {
FLAG_SET_DEFAULT(LoopStripMiningIter, 1000);
}
}
#endif
// CompressedOops not supported
FLAG_SET_DEFAULT(UseCompressedOops, false);
// More events
if (FLAG_IS_DEFAULT(LogEventsBufferEntries)) {
FLAG_SET_DEFAULT(LogEventsBufferEntries, 250);
}
// Verification before startup and after exit not (yet) supported
FLAG_SET_DEFAULT(VerifyDuringStartup, false);
FLAG_SET_DEFAULT(VerifyBeforeExit, false);
if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
FLAG_SET_DEFAULT(ZVerifyRoots, true);
FLAG_SET_DEFAULT(ZVerifyObjects, true);
}
#ifdef ASSERT
// This check slows down testing too much. Turn it off for now.
if (FLAG_IS_DEFAULT(VerifyDependencies)) {
FLAG_SET_DEFAULT(VerifyDependencies, false);
}
#endif
}
size_t ZArguments::heap_virtual_to_physical_ratio() {
return ZVirtualToPhysicalRatio;
}
CollectedHeap* ZArguments::create_heap() {
return new ZCollectedHeap();
}
bool ZArguments::is_supported() {
return is_os_supported();
}