Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions src/hotspot/share/gc/shared/gcArguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@

#include "gc/shared/cardTable.hpp"
#include "gc/shared/gcArguments.hpp"
#include "gc/shared/genArguments.hpp"
#include "logging/log.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/os.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/macros.hpp"

Expand Down Expand Up @@ -56,6 +58,131 @@ void GCArguments::initialize() {
}
}

// Use static initialization to get the default before parsing
static const size_t DefaultHeapBaseMinAddress = HeapBaseMinAddress;

static size_t clamp_by_size_t_max(uint64_t value) {
return (size_t)MIN2(value, (uint64_t)std::numeric_limits<size_t>::max());
}

void GCArguments::set_heap_size() {
// Check if the user has configured any limit on the amount of RAM we may use.
bool has_ram_limit = !FLAG_IS_DEFAULT(MaxRAMPercentage) ||
!FLAG_IS_DEFAULT(MinRAMPercentage) ||
!FLAG_IS_DEFAULT(InitialRAMPercentage);

const physical_memory_size_type avail_mem = os::physical_memory();

// If the maximum heap size has not been set with -Xmx, then set it as
// fraction of the size of physical memory, respecting the maximum and
// minimum sizes of the heap.
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
uint64_t min_memory = (uint64_t)(((double)avail_mem * MinRAMPercentage) / 100);
uint64_t max_memory = (uint64_t)(((double)avail_mem * MaxRAMPercentage) / 100);

const size_t reasonable_min = clamp_by_size_t_max(min_memory);
size_t reasonable_max = clamp_by_size_t_max(max_memory);

if (reasonable_min < MaxHeapSize) {
// Small physical memory, so use a minimum fraction of it for the heap
reasonable_max = reasonable_min;
} else {
// Not-small physical memory, so require a heap at least
// as large as MaxHeapSize
reasonable_max = MAX2(reasonable_max, MaxHeapSize);
}

if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
// Limit the heap size to ErgoHeapSizeLimit
reasonable_max = MIN2(reasonable_max, ErgoHeapSizeLimit);
}

reasonable_max = Arguments::limit_heap_by_allocatable_memory(reasonable_max);

if (!FLAG_IS_DEFAULT(InitialHeapSize)) {
// An initial heap size was specified on the command line,
// so be sure that the maximum size is consistent. Done
// after call to limit_heap_by_allocatable_memory because that
// method might reduce the allocation size.
reasonable_max = MAX2(reasonable_max, InitialHeapSize);
} else if (!FLAG_IS_DEFAULT(MinHeapSize)) {
reasonable_max = MAX2(reasonable_max, MinHeapSize);
}

#ifdef _LP64
if (UseCompressedOops) {
// HeapBaseMinAddress can be greater than default but not less than.
if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) {
if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) {
// matches compressed oops printing flags
log_debug(gc, heap, coops)("HeapBaseMinAddress must be at least %zu "
"(%zuG) which is greater than value given %zu",
DefaultHeapBaseMinAddress,
DefaultHeapBaseMinAddress/G,
HeapBaseMinAddress);
FLAG_SET_ERGO(HeapBaseMinAddress, DefaultHeapBaseMinAddress);
}
}

uintptr_t heap_end = HeapBaseMinAddress + MaxHeapSize;
uintptr_t max_coop_heap = Arguments::max_heap_for_compressed_oops();

// Limit the heap size to the maximum possible when using compressed oops
if (heap_end < max_coop_heap) {
// Heap should be above HeapBaseMinAddress to get zero based compressed
// oops but it should be not less than default MaxHeapSize.
max_coop_heap -= HeapBaseMinAddress;
}

// If the user has configured any limit on the amount of RAM we may use,
// then disable compressed oops if the calculated max exceeds max_coop_heap
// and UseCompressedOops was not specified.
if (reasonable_max > max_coop_heap) {
if (FLAG_IS_ERGO(UseCompressedOops) && has_ram_limit) {
log_debug(gc, heap, coops)("UseCompressedOops disabled due to "
"max heap %zu > compressed oop heap %zu. "
"Please check the setting of MaxRAMPercentage %5.2f.",
reasonable_max, (size_t)max_coop_heap, MaxRAMPercentage);
FLAG_SET_ERGO(UseCompressedOops, false);
} else {
reasonable_max = max_coop_heap;
}
}
}
#endif // _LP64

log_trace(gc, heap)(" Maximum heap size %zu", reasonable_max);
FLAG_SET_ERGO(MaxHeapSize, reasonable_max);
}

// If the minimum or initial heap_size have not been set or requested to be set
// ergonomically, set them accordingly.
if (InitialHeapSize == 0 || MinHeapSize == 0) {
size_t reasonable_minimum = clamp_by_size_t_max((uint64_t)OldSize + (uint64_t)NewSize);
reasonable_minimum = MIN2(reasonable_minimum, MaxHeapSize);
reasonable_minimum = Arguments::limit_heap_by_allocatable_memory(reasonable_minimum);

if (InitialHeapSize == 0) {
uint64_t initial_memory = (uint64_t)(((double)avail_mem * InitialRAMPercentage) / 100);
size_t reasonable_initial = clamp_by_size_t_max(initial_memory);
reasonable_initial = Arguments::limit_heap_by_allocatable_memory(reasonable_initial);

reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, MinHeapSize);
reasonable_initial = MIN2(reasonable_initial, MaxHeapSize);

FLAG_SET_ERGO(InitialHeapSize, (size_t)reasonable_initial);
log_trace(gc, heap)(" Initial heap size %zu", InitialHeapSize);
}

// If the minimum heap size has not been set (via -Xms or -XX:MinHeapSize),
// synchronize with InitialHeapSize to avoid errors with the default value.
if (MinHeapSize == 0) {
FLAG_SET_ERGO(MinHeapSize, MIN2(reasonable_minimum, InitialHeapSize));
log_trace(gc, heap)(" Minimum heap size %zu", MinHeapSize);
}
}
}

void GCArguments::initialize_heap_sizes() {
initialize_alignments();
initialize_heap_flags_and_sizes();
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/gc/shared/gcArguments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class GCArguments {
DEBUG_ONLY(void assert_size_info();)

public:
virtual void set_heap_size();
virtual void initialize();

// Return the (conservative) maximum heap alignment
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ JVMFlag::Error SoftMaxHeapSizeConstraintFunc(size_t value, bool verbose) {
}

JVMFlag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose) {
// If an overflow happened in Arguments::set_heap_size(), MaxHeapSize will have too large a value.
// If an overflow happened in GCArguments::set_heap_size(), MaxHeapSize will have too large a value.
// Check for this by ensuring that MaxHeapSize plus the requested min base address still fit within max_uintx.
if (value > (max_uintx - MaxHeapSize)) {
JVMFlag::printError(verbose,
Expand Down
128 changes: 1 addition & 127 deletions src/hotspot/share/runtime/arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include "gc/shared/gc_globals.hpp"
#include "gc/shared/gcArguments.hpp"
#include "gc/shared/gcConfig.hpp"
#include "gc/shared/genArguments.hpp"
#include "gc/shared/stringdedup/stringDedup.hpp"
#include "gc/shared/tlab_globals.hpp"
#include "jvm.h"
Expand Down Expand Up @@ -1502,131 +1501,6 @@ size_t Arguments::limit_heap_by_allocatable_memory(size_t limit) {
return MIN2(limit, max_allocatable / fraction);
}

// Use static initialization to get the default before parsing
static const size_t DefaultHeapBaseMinAddress = HeapBaseMinAddress;

static size_t clamp_by_size_t_max(uint64_t value) {
return (size_t)MIN2(value, (uint64_t)std::numeric_limits<size_t>::max());
}

void Arguments::set_heap_size() {
// Check if the user has configured any limit on the amount of RAM we may use.
bool has_ram_limit = !FLAG_IS_DEFAULT(MaxRAMPercentage) ||
!FLAG_IS_DEFAULT(MinRAMPercentage) ||
!FLAG_IS_DEFAULT(InitialRAMPercentage);

const physical_memory_size_type avail_mem = os::physical_memory();

// If the maximum heap size has not been set with -Xmx, then set it as
// fraction of the size of physical memory, respecting the maximum and
// minimum sizes of the heap.
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
uint64_t min_memory = (uint64_t)(((double)avail_mem * MinRAMPercentage) / 100);
uint64_t max_memory = (uint64_t)(((double)avail_mem * MaxRAMPercentage) / 100);

const size_t reasonable_min = clamp_by_size_t_max(min_memory);
size_t reasonable_max = clamp_by_size_t_max(max_memory);

if (reasonable_min < MaxHeapSize) {
// Small physical memory, so use a minimum fraction of it for the heap
reasonable_max = reasonable_min;
} else {
// Not-small physical memory, so require a heap at least
// as large as MaxHeapSize
reasonable_max = MAX2(reasonable_max, MaxHeapSize);
}

if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
// Limit the heap size to ErgoHeapSizeLimit
reasonable_max = MIN2(reasonable_max, ErgoHeapSizeLimit);
}

reasonable_max = limit_heap_by_allocatable_memory(reasonable_max);

if (!FLAG_IS_DEFAULT(InitialHeapSize)) {
// An initial heap size was specified on the command line,
// so be sure that the maximum size is consistent. Done
// after call to limit_heap_by_allocatable_memory because that
// method might reduce the allocation size.
reasonable_max = MAX2(reasonable_max, InitialHeapSize);
} else if (!FLAG_IS_DEFAULT(MinHeapSize)) {
reasonable_max = MAX2(reasonable_max, MinHeapSize);
}

#ifdef _LP64
if (UseCompressedOops) {
// HeapBaseMinAddress can be greater than default but not less than.
if (!FLAG_IS_DEFAULT(HeapBaseMinAddress)) {
if (HeapBaseMinAddress < DefaultHeapBaseMinAddress) {
// matches compressed oops printing flags
log_debug(gc, heap, coops)("HeapBaseMinAddress must be at least %zu "
"(%zuG) which is greater than value given %zu",
DefaultHeapBaseMinAddress,
DefaultHeapBaseMinAddress/G,
HeapBaseMinAddress);
FLAG_SET_ERGO(HeapBaseMinAddress, DefaultHeapBaseMinAddress);
}
}

uintptr_t heap_end = HeapBaseMinAddress + MaxHeapSize;
uintptr_t max_coop_heap = max_heap_for_compressed_oops();

// Limit the heap size to the maximum possible when using compressed oops
if (heap_end < max_coop_heap) {
// Heap should be above HeapBaseMinAddress to get zero based compressed
// oops but it should be not less than default MaxHeapSize.
max_coop_heap -= HeapBaseMinAddress;
}

// If the user has configured any limit on the amount of RAM we may use,
// then disable compressed oops if the calculated max exceeds max_coop_heap
// and UseCompressedOops was not specified.
if (reasonable_max > max_coop_heap) {
if (FLAG_IS_ERGO(UseCompressedOops) && has_ram_limit) {
log_debug(gc, heap, coops)("UseCompressedOops disabled due to "
"max heap %zu > compressed oop heap %zu. "
"Please check the setting of MaxRAMPercentage %5.2f.",
reasonable_max, (size_t)max_coop_heap, MaxRAMPercentage);
FLAG_SET_ERGO(UseCompressedOops, false);
} else {
reasonable_max = max_coop_heap;
}
}
}
#endif // _LP64

log_trace(gc, heap)(" Maximum heap size %zu", reasonable_max);
FLAG_SET_ERGO(MaxHeapSize, reasonable_max);
}

// If the minimum or initial heap_size have not been set or requested to be set
// ergonomically, set them accordingly.
if (InitialHeapSize == 0 || MinHeapSize == 0) {
size_t reasonable_minimum = clamp_by_size_t_max((uint64_t)OldSize + (uint64_t)NewSize);
reasonable_minimum = MIN2(reasonable_minimum, MaxHeapSize);
reasonable_minimum = limit_heap_by_allocatable_memory(reasonable_minimum);

if (InitialHeapSize == 0) {
uint64_t initial_memory = (uint64_t)(((double)avail_mem * InitialRAMPercentage) / 100);
size_t reasonable_initial = clamp_by_size_t_max(initial_memory);
reasonable_initial = limit_heap_by_allocatable_memory(reasonable_initial);

reasonable_initial = MAX3(reasonable_initial, reasonable_minimum, MinHeapSize);
reasonable_initial = MIN2(reasonable_initial, MaxHeapSize);

FLAG_SET_ERGO(InitialHeapSize, (size_t)reasonable_initial);
log_trace(gc, heap)(" Initial heap size %zu", InitialHeapSize);
}

// If the minimum heap size has not been set (via -Xms or -XX:MinHeapSize),
// synchronize with InitialHeapSize to avoid errors with the default value.
if (MinHeapSize == 0) {
FLAG_SET_ERGO(MinHeapSize, MIN2(reasonable_minimum, InitialHeapSize));
log_trace(gc, heap)(" Minimum heap size %zu", MinHeapSize);
}
}
}

// This option inspects the machine and attempts to set various
// parameters to be optimal for long-running, memory allocation
// intensive jobs. It is intended for machines with large
Expand Down Expand Up @@ -3802,7 +3676,7 @@ jint Arguments::apply_ergo() {
if (result != JNI_OK) return result;

// Set heap size based on available physical memory
set_heap_size();
GCConfig::arguments()->set_heap_size();

GCConfig::arguments()->initialize();

Expand Down
3 changes: 1 addition & 2 deletions src/hotspot/share/runtime/arguments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class Arguments : AllStatic {
friend class JvmtiExport;
friend class ArgumentsTest;
friend class LargeOptionsTest;
friend class GCArguments;
public:
// Operation modi
enum Mode {
Expand Down Expand Up @@ -277,8 +278,6 @@ class Arguments : AllStatic {
// memory this process is currently allowed to use. It also takes
// the virtual-to-physical ratio of the current GC into account.
static size_t limit_heap_by_allocatable_memory(size_t size);
// Setup heap size
static void set_heap_size();

// Bytecode rewriting
static void set_bytecode_flags();
Expand Down