8134995: [REDO] GC: implement ranges (optionally constraints) for those flags that have them missing
Summary: Add ranges and constraint functions for GC flags.
Reviewed-by: kbarrett, jmasa, jwilhelm, gziemski, zmajo
--- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp Mon Oct 05 14:56:19 2015 -0700
@@ -26,6 +26,7 @@
#define SHARE_VM_GC_G1_G1_GLOBALS_HPP
#include "runtime/globals.hpp"
+#include <float.h> // for DBL_MAX
//
// Defines all globals flags used by the garbage-first compiler.
//
@@ -61,6 +62,7 @@
"update buffer processing info " \
"(0 means do not periodically generate this info); " \
"it also requires -XX:+G1SummarizeRSetStats") \
+ range(0, max_intx) \
\
diagnostic(bool, G1TraceConcRefinement, false, \
"Trace G1 concurrent refinement") \
@@ -71,7 +73,7 @@
product(double, G1ConcMarkStepDurationMillis, 10.0, \
"Target duration of individual concurrent marking steps " \
"in milliseconds.") \
- range(1.0, (double)max_uintx) \
+ range(1.0, DBL_MAX) \
\
product(intx, G1RefProcDrainInterval, 10, \
"The number of discovered reference objects to process before " \
@@ -89,9 +91,11 @@
\
product(size_t, G1SATBBufferSize, 1*K, \
"Number of entries in an SATB log buffer.") \
+ range(1, max_uintx) \
\
develop(intx, G1SATBProcessCompletedThreshold, 20, \
"Number of completed buffers that triggers log processing.") \
+ range(0, max_jint) \
\
product(uintx, G1SATBBufferEnqueueingThresholdPercent, 60, \
"Before enqueueing them, each mutator thread tries to do some " \
@@ -114,26 +118,31 @@
\
product(size_t, G1UpdateBufferSize, 256, \
"Size of an update buffer") \
+ range(1, NOT_LP64(32*M) LP64_ONLY(1*G)) \
\
product(intx, G1ConcRefinementYellowZone, 0, \
"Number of enqueued update buffers that will " \
"trigger concurrent processing. Will be selected ergonomically " \
"by default.") \
+ range(0, max_intx) \
\
product(intx, G1ConcRefinementRedZone, 0, \
"Maximum number of enqueued update buffers before mutator " \
"threads start processing new ones instead of enqueueing them. " \
"Will be selected ergonomically by default. Zero will disable " \
"concurrent processing.") \
+ range(0, max_intx) \
\
product(intx, G1ConcRefinementGreenZone, 0, \
"The number of update buffers that are left in the queue by the " \
"concurrent processing threads. Will be selected ergonomically " \
"by default.") \
+ range(0, max_intx) \
\
product(intx, G1ConcRefinementServiceIntervalMillis, 300, \
"The last concurrent refinement thread wakes up every " \
"specified number of milliseconds to do miscellaneous work.") \
+ range(0, max_jint) \
\
product(intx, G1ConcRefinementThresholdStep, 0, \
"Each time the rset update queue increases by this amount " \
@@ -143,6 +152,7 @@
product(intx, G1RSetUpdatingPauseTimePercent, 10, \
"A target percentage of time that is allowed to be spend on " \
"process RS update buffers during the collection pause.") \
+ range(0, 100) \
\
product(bool, G1UseAdaptiveConcRefinement, true, \
"Select green, yellow and red zones adaptively to meet the " \
@@ -158,18 +168,24 @@
\
develop(intx, G1RSetRegionEntriesBase, 256, \
"Max number of regions in a fine-grain table per MB.") \
+ range(1, max_jint/wordSize) \
\
product(intx, G1RSetRegionEntries, 0, \
"Max number of regions for which we keep bitmaps." \
"Will be set ergonomically by default") \
+ range(0, max_jint/wordSize) \
+ constraint(G1RSetRegionEntriesConstraintFunc,AfterErgo) \
\
develop(intx, G1RSetSparseRegionEntriesBase, 4, \
"Max number of entries per region in a sparse table " \
"per MB.") \
+ range(1, max_jint/wordSize) \
\
product(intx, G1RSetSparseRegionEntries, 0, \
"Max number of entries per region in a sparse table." \
"Will be set ergonomically by default.") \
+ range(0, max_jint/wordSize) \
+ constraint(G1RSetSparseRegionEntriesConstraintFunc,AfterErgo) \
\
develop(bool, G1RecordHRRSOops, false, \
"When true, record recent calls to rem set operations.") \
@@ -180,6 +196,7 @@
develop(intx, G1MaxVerifyFailures, -1, \
"The maximum number of verification failures to print. " \
"-1 means print all.") \
+ range(-1, max_jint) \
\
develop(bool, G1ScrubRemSets, true, \
"When true, do RS scrubbing after cleanup.") \
@@ -193,11 +210,13 @@
develop(intx, G1YoungSurvRateNumRegionsSummary, 0, \
"the number of regions for which we'll print a surv rate " \
"summary.") \
+ range(0, max_intx) \
+ constraint(G1YoungSurvRateNumRegionsSummaryConstraintFunc,AfterErgo)\
\
product(uintx, G1ReservePercent, 10, \
"It determines the minimum reserve we should have in the heap " \
"to minimize the probability of promotion failure.") \
- range(0, 100) \
+ range(0, 50) \
\
diagnostic(bool, G1PrintHeapRegions, false, \
"If set G1 will print information on which regions are being " \
@@ -215,10 +234,13 @@
\
product(size_t, G1HeapRegionSize, 0, \
"Size of the G1 regions.") \
+ range(0, 32*M) \
+ constraint(G1HeapRegionSizeConstraintFunc,AfterMemoryInit) \
\
product(uintx, G1ConcRefinementThreads, 0, \
"If non-0 is the number of parallel rem set update threads, " \
"otherwise the value is determined ergonomically.") \
+ range(0, (max_jint-1)/wordSize) \
\
develop(bool, G1VerifyCTCleanup, false, \
"Verify card table cleanup.") \
@@ -226,6 +248,7 @@
product(size_t, G1RSetScanBlockSize, 64, \
"Size of a work unit of cards claimed by a worker thread" \
"during RSet scanning.") \
+ range(1, max_uintx) \
\
develop(uintx, G1SecondaryFreeListAppendLength, 5, \
"The number of regions we will add to the secondary free list " \
@@ -262,6 +285,7 @@
experimental(uintx, G1NewSizePercent, 5, \
"Percentage (0-100) of the heap size to use as default " \
"minimum young gen size.") \
+ range(0, 100) \
constraint(G1NewSizePercentConstraintFunc,AfterErgo) \
\
experimental(uintx, G1MixedGCLiveThresholdPercent, 85, \
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Oct 05 14:56:19 2015 -0700
@@ -794,8 +794,10 @@
}
static bool set_fp_numeric_flag(const char* name, char* value, Flag::Flags origin) {
- double v;
- if (sscanf(value, "%lf", &v) != 1) {
+ char* end;
+ errno = 0;
+ double v = strtod(value, &end);
+ if ((errno != 0) || (*end != 0)) {
return false;
}
@@ -979,9 +981,9 @@
return set_string_flag(real_name, value, origin);
}
-#define SIGNED_FP_NUMBER_RANGE "[-0123456789.]"
+#define SIGNED_FP_NUMBER_RANGE "[-0123456789.eE+]"
#define SIGNED_NUMBER_RANGE "[-0123456789]"
-#define NUMBER_RANGE "[0123456789]"
+#define NUMBER_RANGE "[0123456789eE+-]"
char value[BUFLEN + 1];
char value2[BUFLEN + 1];
if (sscanf(arg, "%" XSTR(BUFLEN) NAME_RANGE "=" "%" XSTR(BUFLEN) SIGNED_NUMBER_RANGE "." "%" XSTR(BUFLEN) NUMBER_RANGE "%c", name, value, value2, &dummy) == 3) {
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.cpp Mon Oct 05 14:56:19 2015 -0700
@@ -220,7 +220,7 @@
#define EMIT_CONSTRAINT_CHECK(func, type) , func, CommandLineFlagConstraint::type
// the "name" argument must be a string literal
-#define INITIAL_CONSTRAINTS_SIZE 16
+#define INITIAL_CONSTRAINTS_SIZE 40
GrowableArray<CommandLineFlagConstraint*>* CommandLineFlagConstraintList::_constraints = NULL;
CommandLineFlagConstraint::ConstraintType CommandLineFlagConstraintList::_validating_type = CommandLineFlagConstraint::AtParse;
@@ -274,7 +274,7 @@
EMIT_CONSTRAINT_CHECK));
#endif // COMPILER2
-#ifndef INCLUDE_ALL_GCS
+#if INCLUDE_ALL_GCS
emit_constraint_no(NULL G1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
EMIT_CONSTRAINT_PRODUCT_FLAG,
@@ -305,10 +305,7 @@
// Check constraints for specific constraint type.
bool CommandLineFlagConstraintList::check_constraints(CommandLineFlagConstraint::ConstraintType type) {
- // Skip if we already checked.
- if (type < _validating_type) {
- return true;
- }
+ guarantee(type > _validating_type, "Constraint check is out of order.");
_validating_type = type;
bool status = true;
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintList.hpp Mon Oct 05 14:56:19 2015 -0700
@@ -54,9 +54,9 @@
enum ConstraintType {
// Will be validated during argument processing (Arguments::parse_argument).
AtParse = 0,
- // Will be validated by CommandLineFlags::check_constraints_of_after_ergo().
- AfterErgo = 1,
- // Will be validated by CommandLineFlags::check_constraints_of_after_memory_init().
+ // Will be validated by CommandLineFlagConstraintList::check_constraints(AfterErgo).
+ AfterErgo = 1,
+ // Will be validated by CommandLineFlagConstraintList::check_constraints(AfterMemoryInit).
AfterMemoryInit = 2
};
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp Mon Oct 05 14:56:19 2015 -0700
@@ -23,16 +23,19 @@
*/
#include "precompiled.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/collectorPolicy.hpp"
+#include "gc/shared/threadLocalAllocBuffer.hpp"
#include "runtime/arguments.hpp"
#include "runtime/commandLineFlagConstraintsGC.hpp"
#include "runtime/commandLineFlagRangeList.hpp"
#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
#include "utilities/defaultStream.hpp"
#if INCLUDE_ALL_GCS
#include "gc/g1/g1_globals.hpp"
#include "gc/g1/heapRegionBounds.inline.hpp"
-#include "gc/parallel/parallelScavengeHeap.hpp"
#include "gc/shared/plab.hpp"
#endif // INCLUDE_ALL_GCS
#ifdef COMPILER1
@@ -42,6 +45,71 @@
#include "opto/c2_globals.hpp"
#endif // COMPILER2
+// Some flags that have default values that indicate that the
+// JVM should automatically determine an appropriate value
+// for that flag. In those cases it is only appropriate for the
+// constraint checking to be done if the user has specified the
+// value(s) of the flag(s) on the command line. In the constraint
+// checking functions, FLAG_IS_CMDLINE() is used to check if
+// the flag has been set by the user and so should be checked.
+
+#if INCLUDE_ALL_GCS
+static Flag::Error ParallelGCThreadsAndCMSWorkQueueDrainThreshold(uint threads, uintx threshold, bool verbose) {
+ // CMSWorkQueueDrainThreshold is verified to be less than max_juint
+ if (UseConcMarkSweepGC && (threads > (uint)(max_jint / (uint)threshold))) {
+ CommandLineError::print(verbose,
+ "ParallelGCThreads (" UINT32_FORMAT ") or CMSWorkQueueDrainThreshold ("
+ UINTX_FORMAT ") is too large\n",
+ threads, threshold);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ return Flag::SUCCESS;
+}
+#endif
+
+// As ParallelGCThreads differs among GC modes, we need constraint function.
+Flag::Error ParallelGCThreadsConstraintFunc(uint value, bool verbose) {
+ Flag::Error status = Flag::SUCCESS;
+
+#if INCLUDE_ALL_GCS
+ // Parallel GC passes ParallelGCThreads when creating GrowableArray as 'int' type parameter.
+ // So can't exceed with "max_jint"
+ if (UseParallelGC && (value > (uint)max_jint)) {
+ CommandLineError::print(verbose,
+ "ParallelGCThreads (" UINT32_FORMAT ") must be "
+ "less than or equal to " UINT32_FORMAT " for Parallel GC\n",
+ value, max_jint);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ // To avoid overflow at ParScanClosure::do_oop_work.
+ if (UseConcMarkSweepGC && (value > (max_jint / 10))) {
+ CommandLineError::print(verbose,
+ "ParallelGCThreads (" UINT32_FORMAT ") must be "
+ "less than or equal to " UINT32_FORMAT " for CMS GC\n",
+ value, (max_jint / 10));
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ status = ParallelGCThreadsAndCMSWorkQueueDrainThreshold(value, CMSWorkQueueDrainThreshold, verbose);
+#endif
+ return status;
+}
+
+// As ConcGCThreads should be smaller than ParallelGCThreads,
+// we need constraint function.
+Flag::Error ConcGCThreadsConstraintFunc(uint value, bool verbose) {
+#if INCLUDE_ALL_GCS
+ // CMS and G1 GCs use ConcGCThreads.
+ if ((UseConcMarkSweepGC || UseG1GC) && (value > ParallelGCThreads)) {
+ CommandLineError::print(verbose,
+ "ConcGCThreads (" UINT32_FORMAT ") must be "
+ "less than or equal to ParallelGCThreads (" UINT32_FORMAT ")\n",
+ value, ParallelGCThreads);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif
+ return Flag::SUCCESS;
+}
+
static Flag::Error MinPLABSizeBounds(const char* name, size_t value, bool verbose) {
#if INCLUDE_ALL_GCS
if ((UseConcMarkSweepGC || UseG1GC) && (value < PLAB::min_size())) {
@@ -69,16 +137,40 @@
}
static Flag::Error MinMaxPLABSizeBounds(const char* name, size_t value, bool verbose) {
- if (MinPLABSizeBounds(name, value, verbose) == Flag::SUCCESS) {
+ Flag::Error status = MinPLABSizeBounds(name, value, verbose);
+
+ if (status == Flag::SUCCESS) {
return MaxPLABSizeBounds(name, value, verbose);
}
- return Flag::VIOLATES_CONSTRAINT;
+ return status;
}
Flag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose) {
return MinMaxPLABSizeBounds("YoungPLABSize", value, verbose);
}
+Flag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose) {
+ Flag::Error status = Flag::SUCCESS;
+
+#if INCLUDE_ALL_GCS
+ if (UseConcMarkSweepGC) {
+ if (value == 0) {
+ CommandLineError::print(verbose,
+ "OldPLABSize (" SIZE_FORMAT ") must be greater than 0",
+ value);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ // For CMS, OldPLABSize is the number of free blocks of a given size that are used when
+ // replenishing the local per-worker free list caches.
+ // For more details, please refer to Arguments::set_cms_and_parnew_gc_flags().
+ status = MaxPLABSizeBounds("OldPLABSize", value, verbose);
+ } else {
+ status = MinMaxPLABSizeBounds("OldPLABSize", value, verbose);
+ }
+#endif
+ return status;
+}
+
Flag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose) {
if (value > MaxHeapFreeRatio) {
CommandLineError::print(verbose,
@@ -103,6 +195,23 @@
}
}
+static Flag::Error CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(size_t maxHeap, intx softRef, bool verbose) {
+ if ((softRef > 0) && ((maxHeap / M) > (max_uintx / softRef))) {
+ CommandLineError::print(verbose,
+ "Desired lifetime of SoftReferences cannot be expressed correctly. "
+ "MaxHeapSize (" SIZE_FORMAT ") or SoftRefLRUPolicyMSPerMB "
+ "(" INTX_FORMAT ") is too large\n",
+ maxHeap, softRef);
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
+
+Flag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose) {
+ return CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(MaxHeapSize, value, verbose);
+}
+
Flag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
if (value > MaxMetaspaceFreeRatio) {
CommandLineError::print(verbose,
@@ -127,45 +236,111 @@
}
}
-// GC workaround for "-XX:+UseConcMarkSweepGC"
-// which sets InitialTenuringThreshold to 7 but leaves MaxTenuringThreshold remaining at 6
-// and therefore would invalidate the constraint
-#define UseConcMarkSweepGCWorkaroundIfNeeded(initial, max) { \
- if ((initial == 7) && (max == 6)) { \
- return Flag::SUCCESS; \
- } \
+Flag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+ // InitialTenuringThreshold is only used for ParallelGC.
+ if (UseParallelGC && (value > MaxTenuringThreshold)) {
+ CommandLineError::print(verbose,
+ "InitialTenuringThreshold (" UINTX_FORMAT ") must be "
+ "less than or equal to MaxTenuringThreshold (" UINTX_FORMAT ")\n",
+ value, MaxTenuringThreshold);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif
+ return Flag::SUCCESS;
}
-Flag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose) {
- UseConcMarkSweepGCWorkaroundIfNeeded(value, MaxTenuringThreshold);
+Flag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+ // As only ParallelGC uses InitialTenuringThreshold,
+ // we don't need to compare InitialTenuringThreshold with MaxTenuringThreshold.
+ if (UseParallelGC && (value < InitialTenuringThreshold)) {
+ CommandLineError::print(verbose,
+ "MaxTenuringThreshold (" UINTX_FORMAT ") must be "
+ "greater than or equal to InitialTenuringThreshold (" UINTX_FORMAT ")\n",
+ value, InitialTenuringThreshold);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif
- if (value > MaxTenuringThreshold) {
+ // MaxTenuringThreshold=0 means NeverTenure=false && AlwaysTenure=true
+ if ((value == 0) && (NeverTenure || !AlwaysTenure)) {
CommandLineError::print(verbose,
- "InitialTenuringThreshold (" UINTX_FORMAT ") must be "
- "less than or equal to MaxTenuringThreshold (" UINTX_FORMAT ")\n",
- value, MaxTenuringThreshold);
+ "MaxTenuringThreshold (0) should match to NeverTenure=false "
+ "&& AlwaysTenure=true. But we have NeverTenure=%s "
+ "AlwaysTenure=%s\n",
+ NeverTenure ? "true" : "false",
+ AlwaysTenure ? "true" : "false");
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ return Flag::SUCCESS;
+}
+
+#if INCLUDE_ALL_GCS
+Flag::Error G1RSetRegionEntriesConstraintFunc(intx value, bool verbose) {
+ if (!UseG1GC) return Flag::SUCCESS;
+
+ // Default value of G1RSetRegionEntries=0 means will be set ergonomically.
+ // Minimum value is 1.
+ if (FLAG_IS_CMDLINE(G1RSetRegionEntries) && (value < 1)) {
+ CommandLineError::print(verbose,
+ "G1RSetRegionEntries (" INTX_FORMAT ") must be "
+ "greater than or equal to 1\n",
+ value);
return Flag::VIOLATES_CONSTRAINT;
} else {
return Flag::SUCCESS;
}
}
-Flag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose) {
- UseConcMarkSweepGCWorkaroundIfNeeded(InitialTenuringThreshold, value);
+Flag::Error G1RSetSparseRegionEntriesConstraintFunc(intx value, bool verbose) {
+ if (!UseG1GC) return Flag::SUCCESS;
- if (value < InitialTenuringThreshold) {
+ // Default value of G1RSetSparseRegionEntries=0 means will be set ergonomically.
+ // Minimum value is 1.
+ if (FLAG_IS_CMDLINE(G1RSetSparseRegionEntries) && (value < 1)) {
CommandLineError::print(verbose,
- "MaxTenuringThreshold (" UINTX_FORMAT ") must be "
- "greater than or equal to InitialTenuringThreshold (" UINTX_FORMAT ")\n",
- value, InitialTenuringThreshold);
+ "G1RSetSparseRegionEntries (" INTX_FORMAT ") must be "
+ "greater than or equal to 1\n",
+ value);
return Flag::VIOLATES_CONSTRAINT;
} else {
return Flag::SUCCESS;
}
}
-#if INCLUDE_ALL_GCS
+Flag::Error G1YoungSurvRateNumRegionsSummaryConstraintFunc(intx value, bool verbose) {
+ if (!UseG1GC) return Flag::SUCCESS;
+
+ if (value > (intx)HeapRegionBounds::target_number()) {
+ CommandLineError::print(verbose,
+ "G1YoungSurvRateNumRegionsSummary (" INTX_FORMAT ") must be "
+ "less than or equal to region count (" SIZE_FORMAT ")\n",
+ value, HeapRegionBounds::target_number());
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
+
+Flag::Error G1HeapRegionSizeConstraintFunc(size_t value, bool verbose) {
+ if (!UseG1GC) return Flag::SUCCESS;
+
+ // Default value of G1HeapRegionSize=0 means will be set ergonomically.
+ if (FLAG_IS_CMDLINE(G1HeapRegionSize) && (value < HeapRegionBounds::min_size())) {
+ CommandLineError::print(verbose,
+ "G1HeapRegionSize (" SIZE_FORMAT ") must be "
+ "greater than or equal to ergonomic heap region minimum size\n",
+ value);
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
+
Flag::Error G1NewSizePercentConstraintFunc(uintx value, bool verbose) {
+ if (!UseG1GC) return Flag::SUCCESS;
+
if (value > G1MaxNewSizePercent) {
CommandLineError::print(verbose,
"G1NewSizePercent (" UINTX_FORMAT ") must be "
@@ -178,6 +353,8 @@
}
Flag::Error G1MaxNewSizePercentConstraintFunc(uintx value, bool verbose) {
+ if (!UseG1GC) return Flag::SUCCESS;
+
if (value < G1NewSizePercent) {
CommandLineError::print(verbose,
"G1MaxNewSizePercent (" UINTX_FORMAT ") must be "
@@ -188,15 +365,56 @@
return Flag::SUCCESS;
}
}
+#endif // INCLUDE_ALL_GCS
-#endif // INCLUDE_ALL_GCS
+Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+ if (UseConcMarkSweepGC && (value > ((uintx)max_jint / (uintx)ParallelGCThreads))) {
+ CommandLineError::print(verbose,
+ "ParGCStridesPerThread (" UINTX_FORMAT ") must be "
+ "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
+ value, ((uintx)max_jint / (uintx)ParallelGCThreads));
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif
+ return Flag::SUCCESS;
+}
Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose) {
- if (value > CMSOldPLABMax) {
+ Flag::Error status = Flag::SUCCESS;
+
+#if INCLUDE_ALL_GCS
+ if (UseConcMarkSweepGC) {
+ if (value > CMSOldPLABMax) {
+ CommandLineError::print(verbose,
+ "CMSOldPLABMin (" SIZE_FORMAT ") must be "
+ "less than or equal to CMSOldPLABMax (" SIZE_FORMAT ")\n",
+ value, CMSOldPLABMax);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ status = MaxPLABSizeBounds("CMSOldPLABMin", value, verbose);
+ }
+#endif
+ return status;
+}
+
+Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose) {
+ Flag::Error status = Flag::SUCCESS;
+
+#if INCLUDE_ALL_GCS
+ if (UseConcMarkSweepGC) {
+ status = MaxPLABSizeBounds("CMSOldPLABMax", value, verbose);
+ }
+#endif
+ return status;
+}
+
+Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose) {
+ if (value > MarkStackSizeMax) {
CommandLineError::print(verbose,
- "CMSOldPLABMin (" SIZE_FORMAT ") must be "
- "less than or equal to CMSOldPLABMax (" SIZE_FORMAT ")\n",
- value, CMSOldPLABMax);
+ "MarkStackSize (" SIZE_FORMAT ") must be "
+ "less than or equal to MarkStackSizeMax (" SIZE_FORMAT ")\n",
+ value, MarkStackSizeMax);
return Flag::VIOLATES_CONSTRAINT;
} else {
return Flag::SUCCESS;
@@ -204,23 +422,212 @@
}
Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) {
- if (value <= CMSPrecleanNumerator) {
+#if INCLUDE_ALL_GCS
+ if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) {
CommandLineError::print(verbose,
"CMSPrecleanDenominator (" UINTX_FORMAT ") must be "
"strickly greater than CMSPrecleanNumerator (" UINTX_FORMAT ")\n",
value, CMSPrecleanNumerator);
return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif
+ return Flag::SUCCESS;
+}
+
+Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+ if (UseConcMarkSweepGC && (value >= CMSPrecleanDenominator)) {
+ CommandLineError::print(verbose,
+ "CMSPrecleanNumerator (" UINTX_FORMAT ") must be "
+ "less than CMSPrecleanDenominator (" UINTX_FORMAT ")\n",
+ value, CMSPrecleanDenominator);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif
+ return Flag::SUCCESS;
+}
+
+Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+ if (UseConcMarkSweepGC) {
+ return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(ParallelGCThreads, value, verbose);
+ }
+#endif
+ return Flag::SUCCESS;
+}
+
+Flag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+ if (UseG1GC && FLAG_IS_CMDLINE(MaxGCPauseMillis) && (value >= GCPauseIntervalMillis)) {
+ CommandLineError::print(verbose,
+ "MaxGCPauseMillis (" UINTX_FORMAT ") must be "
+ "less than GCPauseIntervalMillis (" UINTX_FORMAT ")\n",
+ value, GCPauseIntervalMillis);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif
+
+ return Flag::SUCCESS;
+}
+
+Flag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ if (FLAG_IS_CMDLINE(GCPauseIntervalMillis)) {
+ if (value < 1) {
+ CommandLineError::print(verbose,
+ "GCPauseIntervalMillis (" UINTX_FORMAT ") must be "
+ "greater than or equal to 1\n",
+ value);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ if (value <= MaxGCPauseMillis) {
+ CommandLineError::print(verbose,
+ "GCPauseIntervalMillis (" UINTX_FORMAT ") must be "
+ "greater than MaxGCPauseMillis (" UINTX_FORMAT ")\n",
+ value, MaxGCPauseMillis);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ }
+ }
+#endif
+ return Flag::SUCCESS;
+}
+
+Flag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
+ size_t aligned_max = (size_t)align_size_down(max_uintx/2, Metaspace::reserve_alignment_words());
+ if (value > aligned_max) {
+ CommandLineError::print(verbose,
+ "InitialBootClassLoaderMetaspaceSize (" SIZE_FORMAT ") must be "
+ "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
+ value, aligned_max);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ return Flag::SUCCESS;
+}
+
+static Flag::Error MaxSizeForHeapAlignment(const char* name, size_t value, bool verbose) {
+ // For G1 GC, we don't know until G1CollectorPolicy is created.
+ size_t heap_alignment;
+
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ heap_alignment = HeapRegionBounds::max_size();
+ } else
+#endif
+ {
+ heap_alignment = CollectorPolicy::compute_heap_alignment();
+ }
+
+ // Not to overflow 'align_size_up(value, _heap_alignment) used from CollectorPolicy::initialize_flags()'.
+ size_t aligned_max = ((max_uintx - heap_alignment) & ~(heap_alignment-1));
+ if (value > aligned_max) {
+ CommandLineError::print(verbose,
+ "%s (" SIZE_FORMAT ") must be "
+ "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
+ name, value, aligned_max);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ return Flag::SUCCESS;
+}
+
+Flag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose) {
+ return MaxSizeForHeapAlignment("InitialHeapSize", value, verbose);
+}
+
+Flag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose) {
+ Flag::Error status = MaxSizeForHeapAlignment("MaxHeapSize", value, verbose);
+
+ if (status == Flag::SUCCESS) {
+ status = CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(value, SoftRefLRUPolicyMSPerMB, verbose);
+ }
+ return status;
+}
+
+Flag::Error NewSizeConstraintFunc(size_t value, bool verbose) {
+#ifdef _LP64
+#if INCLUDE_ALL_GCS
+ // Overflow would happen for uint type variable of YoungGenSizer::_min_desired_young_length
+ // when the value to be assigned exceeds uint range.
+ // i.e. result of '(uint)(NewSize / region size(1~32MB))'
+ // So maximum of NewSize should be 'max_juint * 1M'
+ if (UseG1GC && (value > (max_juint * 1 * M))) {
+ CommandLineError::print(verbose,
+ "NewSize (" SIZE_FORMAT ") must be less than ergonomic maximum value\n",
+ value);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+#endif // INCLUDE_ALL_GCS
+#endif // _LP64
+ return Flag::SUCCESS;
+}
+
+Flag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose) {
+ // At least, alignment reserve area is needed.
+ if (value < ThreadLocalAllocBuffer::alignment_reserve_in_bytes()) {
+ CommandLineError::print(verbose,
+ "MinTLABSize (" SIZE_FORMAT ") must be "
+ "greater than or equal to reserved area in TLAB (" SIZE_FORMAT ")\n",
+ value, ThreadLocalAllocBuffer::alignment_reserve_in_bytes());
+ return Flag::VIOLATES_CONSTRAINT;
} else {
return Flag::SUCCESS;
}
}
-Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose) {
- if (value > (CMSPrecleanDenominator - 1)) {
+Flag::Error TLABSizeConstraintFunc(size_t value, bool verbose) {
+ // Skip for default value of zero which means set ergonomically.
+ if (FLAG_IS_CMDLINE(TLABSize)) {
+ if (value < MinTLABSize) {
+ CommandLineError::print(verbose,
+ "TLABSize (" SIZE_FORMAT ") must be "
+ "greater than or equal to MinTLABSize (" SIZE_FORMAT ")\n",
+ value, MinTLABSize);
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
+ CommandLineError::print(verbose,
+ "TLABSize (" SIZE_FORMAT ") must be "
+ "less than or equal to ergonomic TLAB maximum size (" SIZE_FORMAT ")\n",
+ value, (ThreadLocalAllocBuffer::max_size() * HeapWordSize));
+ return Flag::VIOLATES_CONSTRAINT;
+ }
+ }
+ return Flag::SUCCESS;
+}
+
+Flag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose) {
+ if (FLAG_IS_CMDLINE(SurvivorRatio) &&
+ (value > (MaxHeapSize / Universe::heap()->collector_policy()->space_alignment()))) {
CommandLineError::print(verbose,
- "CMSPrecleanNumerator (" UINTX_FORMAT ") must be "
- "less than or equal to CMSPrecleanDenominator - 1 (" UINTX_FORMAT ")\n",
- value, CMSPrecleanDenominator - 1);
+ "SurvivorRatio (" UINTX_FORMAT ") must be "
+ "less than or equal to ergonomic SurvivorRatio maximum (" SIZE_FORMAT ")\n",
+ value,
+ (MaxHeapSize / Universe::heap()->collector_policy()->space_alignment()));
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
+
+Flag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose) {
+ if (value > MaxMetaspaceSize) {
+ CommandLineError::print(verbose,
+ "MetaspaceSize (" SIZE_FORMAT ") must be "
+ "less than or equal to MaxMetaspaceSize (" SIZE_FORMAT ")\n",
+ value, MaxMetaspaceSize);
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
+
+Flag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
+ if (value < MetaspaceSize) {
+ CommandLineError::print(verbose,
+ "MaxMetaspaceSize (" SIZE_FORMAT ") must be "
+ "greater than or equal to MetaspaceSize (" SIZE_FORMAT ")\n",
+ value, MaxMetaspaceSize);
return Flag::VIOLATES_CONSTRAINT;
} else {
return Flag::SUCCESS;
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsGC.hpp Mon Oct 05 14:56:19 2015 -0700
@@ -34,27 +34,45 @@
* an appropriate error value.
*/
+Flag::Error ParallelGCThreadsConstraintFunc(uint value, bool verbose);
+Flag::Error ConcGCThreadsConstraintFunc(uint value, bool verbose);
Flag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose);
-
+Flag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose);
Flag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose);
Flag::Error MaxHeapFreeRatioConstraintFunc(uintx value, bool verbose);
-
+Flag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose);
Flag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose);
Flag::Error MaxMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose);
-
Flag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose);
Flag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose);
#if INCLUDE_ALL_GCS
+Flag::Error G1RSetRegionEntriesConstraintFunc(intx value, bool verbose);
+Flag::Error G1RSetSparseRegionEntriesConstraintFunc(intx value, bool verbose);
+Flag::Error G1YoungSurvRateNumRegionsSummaryConstraintFunc(intx value, bool verbose);
+Flag::Error G1HeapRegionSizeConstraintFunc(size_t value, bool verbose);
Flag::Error G1NewSizePercentConstraintFunc(uintx value, bool verbose);
Flag::Error G1MaxNewSizePercentConstraintFunc(uintx value, bool verbose);
#endif // INCLUDE_ALL_GCS
+Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose);
Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose);
-
+Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose);
+Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose);
Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose);
Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose);
-
+Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose);
+Flag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose);
+Flag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose);
+Flag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error NewSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error TLABSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose);
+Flag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose);
Flag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose);
#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSGC_HPP */
--- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp Mon Oct 05 14:56:19 2015 -0700
@@ -278,7 +278,7 @@
// Generate func argument to pass into emit_range_xxx functions
#define EMIT_RANGE_CHECK(a, b) , a, b
-#define INITIAL_RANGES_SIZE 128
+#define INITIAL_RANGES_SIZE 165
GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL;
// Check the ranges of all flags that have them
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Oct 05 14:56:19 2015 -0700
@@ -26,6 +26,7 @@
#define SHARE_VM_RUNTIME_GLOBALS_HPP
#include "utilities/debug.hpp"
+#include <float.h> // for DBL_MAX
// use this for flags that are true per default in the tiered build
// but false in non-tiered builds, and vice versa
@@ -1534,6 +1535,7 @@
\
product(uint, ParallelGCThreads, 0, \
"Number of parallel threads parallel gc will use") \
+ constraint(ParallelGCThreadsConstraintFunc,AfterErgo) \
\
diagnostic(bool, UseSemaphoreGCThreadsSynchronization, true, \
"Use semaphore synchronization for the GC Threads, " \
@@ -1565,14 +1567,7 @@
\
product(uint, ConcGCThreads, 0, \
"Number of threads concurrent gc will use") \
- \
- product(size_t, YoungPLABSize, 4096, \
- "Size of young gen promotion LAB's (in HeapWords)") \
- constraint(YoungPLABSizeConstraintFunc,AfterMemoryInit) \
- \
- product(size_t, OldPLABSize, 1024, \
- "Size of old gen promotion LAB's (in HeapWords), or Number \
- of blocks to attempt to claim when refilling CMS LAB's") \
+ constraint(ConcGCThreadsConstraintFunc,AfterErgo) \
\
product(uintx, GCTaskTimeStampEntries, 200, \
"Number of time stamp entries per gc worker thread") \
@@ -1680,6 +1675,7 @@
"The number of strides per worker thread that we divide up the " \
"card table scanning work into") \
range(1, max_uintx) \
+ constraint(ParGCStridesPerThreadConstraintFunc,AfterErgo) \
\
diagnostic(intx, ParGCCardsPerStrideChunk, 256, \
"The number of cards in each chunk of the parallel chunks used " \
@@ -1702,12 +1698,13 @@
"Maximum size of CMS gen promotion LAB caches per worker " \
"per block size") \
range(1, max_uintx) \
+ constraint(CMSOldPLABMaxConstraintFunc,AfterMemoryInit) \
\
product(size_t, CMSOldPLABMin, 16, \
"Minimum size of CMS gen promotion LAB caches per worker " \
"per block size") \
range(1, max_uintx) \
- constraint(CMSOldPLABMinConstraintFunc,AfterErgo) \
+ constraint(CMSOldPLABMinConstraintFunc,AfterMemoryInit) \
\
product(uintx, CMSOldPLABNumRefills, 4, \
"Nominal number of refills of CMS gen promotion LAB cache " \
@@ -1766,24 +1763,29 @@
product(double, FLSLargestBlockCoalesceProximity, 0.99, \
"CMS: the smaller the percentage the greater the coalescing " \
"force") \
+ range(0.0, 1.0) \
\
product(double, CMSSmallCoalSurplusPercent, 1.05, \
"CMS: the factor by which to inflate estimated demand of small " \
"block sizes to prevent coalescing with an adjoining block") \
+ range(0.0, DBL_MAX) \
\
product(double, CMSLargeCoalSurplusPercent, 0.95, \
"CMS: the factor by which to inflate estimated demand of large " \
"block sizes to prevent coalescing with an adjoining block") \
+ range(0.0, DBL_MAX) \
\
product(double, CMSSmallSplitSurplusPercent, 1.10, \
"CMS: the factor by which to inflate estimated demand of small " \
"block sizes to prevent splitting to supply demand for smaller " \
"blocks") \
+ range(0.0, DBL_MAX) \
\
product(double, CMSLargeSplitSurplusPercent, 1.00, \
"CMS: the factor by which to inflate estimated demand of large " \
"block sizes to prevent splitting to supply demand for smaller " \
"blocks") \
+ range(0.0, DBL_MAX) \
\
product(bool, CMSExtrapolateSweep, false, \
"CMS: cushion for block demand during sweep") \
@@ -1811,9 +1813,11 @@
\
develop(intx, CMSDictionaryChoice, 0, \
"Use BinaryTreeDictionary as default in the CMS generation") \
+ range(0, 2) \
\
product(uintx, CMSIndexedFreeListReplenish, 4, \
"Replenish an indexed free list with this number of chunks") \
+ range(1, max_uintx) \
\
product(bool, CMSReplenishIntermediate, true, \
"Replenish all intermediate free-list caches") \
@@ -1828,14 +1832,15 @@
develop(bool, CMSOverflowEarlyRestoration, false, \
"Restore preserved marks early") \
\
- product(size_t, MarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M), \
- "Size of marking stack") \
- \
/* where does the range max value of (max_jint - 1) come from? */ \
product(size_t, MarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M), \
"Maximum size of marking stack") \
range(1, (max_jint - 1)) \
\
+ product(size_t, MarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M), \
+ "Size of marking stack") \
+ constraint(MarkStackSizeConstraintFunc,AfterErgo) \
+ \
notproduct(bool, CMSMarkStackOverflowALot, false, \
"Simulate frequent marking stack / work queue overflow") \
\
@@ -1848,6 +1853,7 @@
\
product(intx, CMSMaxAbortablePrecleanTime, 5000, \
"Maximum time in abortable preclean (in milliseconds)") \
+ range(0, max_intx) \
\
product(uintx, CMSAbortablePrecleanMinWorkPerIteration, 100, \
"Nominal minimum work per abortable preclean iteration") \
@@ -1855,6 +1861,7 @@
manageable(intx, CMSAbortablePrecleanWaitMillis, 100, \
"Time that we sleep between iterations when not given " \
"enough work per iteration") \
+ range(0, max_intx) \
\
product(size_t, CMSRescanMultiple, 32, \
"Size (in cards) of CMS parallel rescan task") \
@@ -1961,6 +1968,8 @@
\
product(uintx, CMSWorkQueueDrainThreshold, 10, \
"Don't drain below this size per parallel worker/thief") \
+ range(1, max_juint) \
+ constraint(CMSWorkQueueDrainThresholdConstraintFunc,AfterErgo) \
\
manageable(intx, CMSWaitDuration, 2000, \
"Time in milliseconds that CMS thread waits for young GC") \
@@ -2212,9 +2221,11 @@
\
develop(intx, PSAdaptiveSizePolicyResizeVirtualSpaceAlot, -1, \
"Resize the virtual spaces of the young or old generations") \
+ range(-1, 1) \
\
product(uintx, AdaptiveSizeThroughPutPolicy, 0, \
"Policy for changing generation size for throughput goals") \
+ range(0, 1) \
\
develop(bool, PSAdjustTenuredGenForMinorPause, false, \
"Adjust tenured generation to achieve a minor pause goal") \
@@ -2286,9 +2297,12 @@
product(uintx, MaxGCPauseMillis, max_uintx, \
"Adaptive size policy maximum GC pause time goal in millisecond, "\
"or (G1 Only) the maximum GC time per MMU time slice") \
+ range(1, max_uintx) \
+ constraint(MaxGCPauseMillisConstraintFunc,AfterMemoryInit) \
\
product(uintx, GCPauseIntervalMillis, 0, \
"Time slice for MMU specification") \
+ constraint(GCPauseIntervalMillisConstraintFunc,AfterMemoryInit) \
\
product(uintx, MaxGCMinorPauseMillis, max_uintx, \
"Adaptive size policy maximum GC minor pause time goal " \
@@ -2309,6 +2323,7 @@
\
product(uintx, MinSurvivorRatio, 3, \
"Minimum ratio of young generation/survivor space size") \
+ range(3, max_uintx) \
\
product(uintx, InitialSurvivorRatio, 8, \
"Initial ratio of young generation/survivor space size") \
@@ -2332,6 +2347,7 @@
\
develop(uintx, AdaptiveSizePolicyGCTimeLimitThreshold, 5, \
"Number of consecutive collections before gc time limit fires") \
+ range(1, max_uintx) \
\
product(bool, PrintAdaptiveSizePolicy, false, \
"Print information about AdaptiveSizePolicy") \
@@ -2431,6 +2447,7 @@
develop(intx, ConcGCYieldTimeout, 0, \
"If non-zero, assert that GC threads yield within this " \
"number of milliseconds") \
+ range(0, max_intx) \
\
product(bool, PrintReferenceGC, false, \
"Print times spent handling reference objects during GC " \
@@ -2469,6 +2486,8 @@
product(size_t, InitialBootClassLoaderMetaspaceSize, \
NOT_LP64(2200*K) LP64_ONLY(4*M), \
"Initial size of the boot class loader data metaspace") \
+ range(30*K, max_uintx/BytesPerWord) \
+ constraint(InitialBootClassLoaderMetaspaceSizeConstraintFunc, AfterErgo)\
\
product(bool, TraceYoungGenTime, false, \
"Trace accumulated time for young collection") \
@@ -2545,6 +2564,7 @@
experimental(double, ObjectCountCutOffPercent, 0.5, \
"The percentage of the used heap that the instances of a class " \
"must occupy for the class to generate a trace event") \
+ range(0.0, 100.0) \
\
/* GC log rotation setting */ \
\
@@ -3255,15 +3275,18 @@
/* gc parameters */ \
product(size_t, InitialHeapSize, 0, \
"Initial heap size (in bytes); zero means use ergonomics") \
+ constraint(InitialHeapSizeConstraintFunc,AfterErgo) \
\
product(size_t, MaxHeapSize, ScaleForWordSize(96*M), \
"Maximum heap size (in bytes)") \
+ constraint(MaxHeapSizeConstraintFunc,AfterErgo) \
\
product(size_t, OldSize, ScaleForWordSize(4*M), \
"Initial tenured generation size (in bytes)") \
\
product(size_t, NewSize, ScaleForWordSize(1*M), \
"Initial new generation size (in bytes)") \
+ constraint(NewSizeConstraintFunc,AfterErgo) \
\
product(size_t, MaxNewSize, max_uintx, \
"Maximum new generation size (in bytes), max_uintx means set " \
@@ -3273,12 +3296,23 @@
"Maximum size in bytes of objects allocated in DefNew " \
"generation; zero means no maximum") \
\
- product(size_t, TLABSize, 0, \
- "Starting TLAB size (in bytes); zero means set ergonomically") \
- \
product(size_t, MinTLABSize, 2*K, \
"Minimum allowed TLAB size (in bytes)") \
range(1, max_uintx) \
+ constraint(MinTLABSizeConstraintFunc,AfterMemoryInit) \
+ \
+ product(size_t, TLABSize, 0, \
+ "Starting TLAB size (in bytes); zero means set ergonomically") \
+ constraint(TLABSizeConstraintFunc,AfterMemoryInit) \
+ \
+ product(size_t, YoungPLABSize, 4096, \
+ "Size of young gen promotion LAB's (in HeapWords)") \
+ constraint(YoungPLABSizeConstraintFunc,AfterMemoryInit) \
+ \
+ product(size_t, OldPLABSize, 1024, \
+ "Size of old gen promotion LAB's (in HeapWords), or Number " \
+ "of blocks to attempt to claim when refilling CMS LAB's") \
+ constraint(OldPLABSizeConstraintFunc,AfterMemoryInit) \
\
product(uintx, TLABAllocationWeight, 35, \
"Allocation averaging weight") \
@@ -3299,9 +3333,12 @@
\
product(uintx, SurvivorRatio, 8, \
"Ratio of eden/survivor space size") \
+ range(1, max_uintx-2) \
+ constraint(SurvivorRatioConstraintFunc,AfterMemoryInit) \
\
product(uintx, NewRatio, 2, \
"Ratio of old/new generation sizes") \
+ range(0, max_uintx-1) \
\
product_pd(size_t, NewSizeThreadIncrease, \
"Additional size added to desired new generation size per " \
@@ -3309,9 +3346,11 @@
\
product_pd(size_t, MetaspaceSize, \
"Initial size of Metaspaces (in bytes)") \
+ constraint(MetaspaceSizeConstraintFunc,AfterErgo) \
\
product(size_t, MaxMetaspaceSize, max_uintx, \
"Maximum size of Metaspaces (in bytes)") \
+ constraint(MaxMetaspaceSizeConstraintFunc,AfterErgo) \
\
product(size_t, CompressedClassSpaceSize, 1*G, \
"Maximum size of class area in Metaspace when compressed " \
@@ -3334,6 +3373,8 @@
\
product(intx, SoftRefLRUPolicyMSPerMB, 1000, \
"Number of milliseconds per MB of free space in the heap") \
+ range(0, max_intx) \
+ constraint(SoftRefLRUPolicyMSPerMBConstraintFunc,AfterMemoryInit) \
\
product(size_t, MinHeapDeltaBytes, ScaleForWordSize(128*K), \
"The minimum change in heap space due to GC (in bytes)") \
@@ -3365,6 +3406,7 @@
\
diagnostic(intx, VerifyGCLevel, 0, \
"Generation level at which to start +VerifyBefore/AfterGC") \
+ range(0, 1) \
\
product(uintx, MaxTenuringThreshold, 15, \
"Maximum value for tenuring threshold") \
@@ -3423,6 +3465,7 @@
"before changing safepoint polling page to RO ") \
\
product(intx, SafepointSpinBeforeYield, 2000, "(Unstable)") \
+ range(0, max_intx) \
\
product(bool, PSChunkLargeArrays, true, \
"Process large arrays in chunks") \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestG1ConcMarkStepDurationMillis.java Mon Oct 05 14:56:19 2015 -0700
@@ -0,0 +1,110 @@
+/*
+* Copyright (c) 2015, 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.
+*/
+
+/*
+ * @test TestG1ConcMarkStepDurationMillis
+ * @key gc
+ * @requires vm.gc=="null" | vm.gc=="G1"
+ * @summary Tests argument processing for double type flag, G1ConcMarkStepDurationMillis
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.management
+ */
+
+import jdk.test.lib.*;
+import java.util.*;
+import java.util.regex.*;
+
+public class TestG1ConcMarkStepDurationMillis {
+
+ static final int PASS = 0;
+ static final int FAIL_IMPROPER_VALUE = 1;
+ static final int FAIL_OUT_RANGE = 2;
+
+ static final String DOUBLE_1 = "1.0";
+ static final String DOUBLE_MAX = "1.79e+308";
+
+ static final String DOUBLE_NEG_EXP = "1.0e-30";
+ static final String NEG_DOUBLE_1 = "-1.0";
+
+ static final String DOUBLE_INF = "1.79e+309";
+ static final String NEG_DOUBLE_INF = "-1.79e+309";
+ static final String DOUBLE_NAN = "abe+309";
+ static final String WRONG_DOUBLE_1 = "1.79e+308e";
+ static final String WRONG_DOUBLE_2 = "1.79ee+308";
+
+ public static void main(String args[]) throws Exception {
+ // Pass cases
+ runG1ConcMarkStepDurationMillisTest(DOUBLE_1, PASS);
+ runG1ConcMarkStepDurationMillisTest(DOUBLE_MAX, PASS);
+
+ // Fail cases: out of range
+ runG1ConcMarkStepDurationMillisTest(DOUBLE_NEG_EXP, FAIL_OUT_RANGE);
+ runG1ConcMarkStepDurationMillisTest(NEG_DOUBLE_1, FAIL_OUT_RANGE);
+
+ // Fail cases: not double
+ runG1ConcMarkStepDurationMillisTest(DOUBLE_INF, FAIL_IMPROPER_VALUE);
+ runG1ConcMarkStepDurationMillisTest(NEG_DOUBLE_INF, FAIL_IMPROPER_VALUE);
+ runG1ConcMarkStepDurationMillisTest(DOUBLE_NAN, FAIL_IMPROPER_VALUE);
+ runG1ConcMarkStepDurationMillisTest(WRONG_DOUBLE_1, FAIL_IMPROPER_VALUE);
+ runG1ConcMarkStepDurationMillisTest(WRONG_DOUBLE_2, FAIL_IMPROPER_VALUE);
+ }
+
+ private static void runG1ConcMarkStepDurationMillisTest(String expectedValue, int expectedResult) throws Exception {
+ List<String> vmOpts = new ArrayList<>();
+
+ Collections.addAll(vmOpts, "-XX:+UseG1GC", "-XX:G1ConcMarkStepDurationMillis="+expectedValue, "-XX:+PrintFlagsFinal", "-version");
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ output.shouldHaveExitValue(expectedResult == PASS ? 0 : 1);
+ String stdout = output.getStdout();
+ if (expectedResult == PASS) {
+ checkG1ConcMarkStepDurationMillisConsistency(stdout, expectedValue);
+ } else if (expectedResult == FAIL_IMPROPER_VALUE) {
+ output.shouldContain("Improperly specified VM option");
+ } else if (expectedResult == FAIL_OUT_RANGE) {
+ output.shouldContain("outside the allowed range");
+ }
+ }
+
+ private static void checkG1ConcMarkStepDurationMillisConsistency(String output, String expectedValue) {
+ double actualValue = getDoubleValue("G1ConcMarkStepDurationMillis", output);
+
+ if (Double.parseDouble(expectedValue) != actualValue) {
+ throw new RuntimeException(
+ "Actual G1ConcMarkStepDurationMillis(" + Double.toString(actualValue)
+ + ") is not equal to expected value(" + expectedValue + ")");
+ }
+ }
+
+ public static double getDoubleValue(String flag, String where) {
+ Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
+ if (!m.find()) {
+ throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+ }
+ String match = m.group();
+ return Double.parseDouble(match.substring(match.lastIndexOf(" ") + 1, match.length()));
+ }
+}
--- a/hotspot/test/gc/arguments/TestG1HeapRegionSize.java Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/test/gc/arguments/TestG1HeapRegionSize.java Mon Oct 05 14:56:19 2015 -0700
@@ -25,42 +25,59 @@
* @test TestG1HeapRegionSize
* @key gc
* @bug 8021879
+ * @requires vm.gc=="null" | vm.gc=="G1"
* @summary Verify that the flag G1HeapRegionSize is updated properly
* @modules java.management/sun.management
- * @run main/othervm -Xmx64m TestG1HeapRegionSize 1048576
- * @run main/othervm -XX:G1HeapRegionSize=2m -Xmx64m TestG1HeapRegionSize 2097152
- * @run main/othervm -XX:G1HeapRegionSize=3m -Xmx64m TestG1HeapRegionSize 2097152
- * @run main/othervm -XX:G1HeapRegionSize=64m -Xmx256m TestG1HeapRegionSize 33554432
+ * @library /testlibrary
+ * @run main TestG1HeapRegionSize
*/
-import com.sun.management.HotSpotDiagnosticMXBean;
-import com.sun.management.VMOption;
-import java.lang.management.ManagementFactory;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import jdk.test.lib.*;
public class TestG1HeapRegionSize {
- public static void main(String[] args) {
- HotSpotDiagnosticMXBean diagnostic =
- ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
+ private static void checkG1HeapRegionSize(String[] flags, int expectedValue, int exitValue) throws Exception {
+ ArrayList<String> flagList = new ArrayList<String>();
+ flagList.addAll(Arrays.asList(flags));
+ flagList.add("-XX:+UseG1GC");
+ flagList.add("-XX:+PrintFlagsFinal");
+ flagList.add("-version");
- String expectedValue = getExpectedValue(args);
- VMOption option = diagnostic.getVMOption("UseG1GC");
- if (option.getValue().equals("false")) {
- System.out.println("Skipping this test. It is only a G1 test.");
- return;
- }
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flagList.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(exitValue);
- option = diagnostic.getVMOption("G1HeapRegionSize");
- if (!expectedValue.equals(option.getValue())) {
- throw new RuntimeException("Wrong value for G1HeapRegionSize. Expected " + expectedValue + " but got " + option.getValue());
+ if (exitValue == 0) {
+ String stdout = output.getStdout();
+ int flagValue = getFlagValue("G1HeapRegionSize", stdout);
+ if (flagValue != expectedValue) {
+ throw new RuntimeException("Wrong value for G1HeapRegionSize. Expected " + expectedValue + " but got " + flagValue);
+ }
}
}
- private static String getExpectedValue(String[] args) {
- if (args.length != 1) {
- throw new RuntimeException("Wrong number of arguments. Expected 1 but got " + args.length);
+ private static int getFlagValue(String flag, String where) {
+ Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where);
+ if (!m.find()) {
+ throw new RuntimeException("Could not find value for flag " + flag + " in output string");
}
- return args[0];
+ String match = m.group();
+ return Integer.parseInt(match.substring(match.lastIndexOf(" ") + 1, match.length()));
}
+ public static void main(String args[]) throws Exception {
+ final int M = 1024 * 1024;
+
+ checkG1HeapRegionSize(new String[] { "-Xmx64m" /* default is 1m */ }, 1*M, 0);
+ checkG1HeapRegionSize(new String[] { "-Xmx64m", "-XX:G1HeapRegionSize=2m" }, 2*M, 0);
+ checkG1HeapRegionSize(new String[] { "-Xmx64m", "-XX:G1HeapRegionSize=3m" }, 2*M, 0);
+ checkG1HeapRegionSize(new String[] { "-Xmx256m", "-XX:G1HeapRegionSize=32m" }, 32*M, 0);
+ checkG1HeapRegionSize(new String[] { "-Xmx256m", "-XX:G1HeapRegionSize=64m" }, 32*M, 1);
+ }
}
--- a/hotspot/test/gc/arguments/TestHeapFreeRatio.java Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/test/gc/arguments/TestHeapFreeRatio.java Mon Oct 05 14:56:19 2015 -0700
@@ -72,7 +72,7 @@
output.shouldHaveExitValue(1);
break;
case COMBINATION_INVALID:
- output.shouldContain("must be greater than or equal to MinHeapFreeRatio");
+ output.shouldContain("must be less than or equal to MaxHeapFreeRatio");
output.shouldContain("Error");
output.shouldHaveExitValue(1);
break;
--- a/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java Mon Oct 05 14:56:19 2015 -0700
@@ -25,6 +25,7 @@
* @test TestInitialTenuringThreshold
* @key gc
* @bug 8014765
+ * @requires vm.gc=="Parallel"
* @summary Tests argument processing for initial tenuring threshold
* @library /testlibrary
* @modules java.base/sun.misc
@@ -39,6 +40,7 @@
public static void runWithThresholds(int initial, int max, boolean shouldfail) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UseParallelGC",
"-XX:InitialTenuringThreshold=" + String.valueOf(initial),
"-XX:MaxTenuringThreshold=" + String.valueOf(max),
"-version"
--- a/hotspot/test/gc/arguments/TestObjectTenuringFlags.java Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/test/gc/arguments/TestObjectTenuringFlags.java Mon Oct 05 14:56:19 2015 -0700
@@ -25,6 +25,7 @@
* @test TestObjectTenuringFlags
* @key gc
* @bug 6521376
+ * @requires vm.gc=="Parallel"
* @summary Tests argument processing for NeverTenure, AlwaysTenure,
* and MaxTenuringThreshold
* @library /testlibrary
@@ -157,7 +158,7 @@
if (tenuringFlags.length > 0) {
Collections.addAll(vmOpts, tenuringFlags);
}
- Collections.addAll(vmOpts, "-XX:+PrintFlagsFinal", "-version");
+ Collections.addAll(vmOpts, "-XX:+UseParallelGC", "-XX:+PrintFlagsFinal", "-version");
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()]));
OutputAnalyzer output = new OutputAnalyzer(pb.start());
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java Thu Oct 08 12:47:17 2015 +0200
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java Mon Oct 05 14:56:19 2015 -0700
@@ -51,6 +51,14 @@
*/
allOptionsAsMap.remove("CICompilerCount");
+ /*
+ * Exclude below options as their maximum value would consume too much memory
+ * and would affect other tests that run in parallel.
+ */
+ allOptionsAsMap.remove("G1ConcRefinementThreads");
+ allOptionsAsMap.remove("G1RSetRegionEntries");
+ allOptionsAsMap.remove("G1RSetSparseRegionEntries");
+
allOptions = new ArrayList<>(allOptionsAsMap.values());
Asserts.assertGT(allOptions.size(), 0, "Options with ranges not found!");