6843347: Boundary values in some public GC options cause crashes
Summary: Setting some public integer options to specific values causes crashes or undefined GC behavior. This patchset adds the necessary argument checking for these options.
Reviewed-by: jmasa, brutisso
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Wed May 15 11:05:09 2013 +0200
@@ -74,7 +74,7 @@
define_pd_global(bool, UseMembar, false);
// GC Ergo Flags
-define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
+define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
\
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Wed May 15 11:05:09 2013 +0200
@@ -77,7 +77,7 @@
#endif
// GC Ergo Flags
-define_pd_global(intx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread
+define_pd_global(uintx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
\
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp Wed May 15 11:05:09 2013 +0200
@@ -55,7 +55,7 @@
define_pd_global(bool, UseMembar, true);
// GC Ergo Flags
-define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
+define_pd_global(uintx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct)
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed May 15 11:05:09 2013 +0200
@@ -692,8 +692,7 @@
_cmsGen ->init_initiating_occupancy(CMSInitiatingOccupancyFraction, CMSTriggerRatio);
// Clip CMSBootstrapOccupancy between 0 and 100.
- _bootstrap_occupancy = ((double)MIN2((uintx)100, MAX2((uintx)0, CMSBootstrapOccupancy)))
- /(double)100;
+ _bootstrap_occupancy = ((double)CMSBootstrapOccupancy)/(double)100;
_full_gcs_since_conc_gc = 0;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed May 15 11:05:09 2013 +0200
@@ -92,8 +92,8 @@
const bool clear_all_soft_refs =
heap->collector_policy()->should_clear_all_soft_refs();
- int count = (maximum_heap_compaction)?1:MarkSweepAlwaysCompactCount;
- IntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count);
+ uint count = maximum_heap_compaction ? 1 : MarkSweepAlwaysCompactCount;
+ UIntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count);
PSMarkSweep::invoke_no_policy(clear_all_soft_refs || maximum_heap_compaction);
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Wed May 15 11:05:09 2013 +0200
@@ -88,8 +88,7 @@
* by the MarkSweepAlwaysCompactCount parameter. This is a significant
* performance improvement!
*/
- bool skip_dead = (MarkSweepAlwaysCompactCount < 1)
- || ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0);
+ bool skip_dead = ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0);
size_t allowed_deadspace = 0;
if (skip_dead) {
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Wed May 15 11:05:09 2013 +0200
@@ -30,7 +30,7 @@
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
-unsigned int MarkSweep::_total_invocations = 0;
+uint MarkSweep::_total_invocations = 0;
Stack<oop, mtGC> MarkSweep::_marking_stack;
Stack<ObjArrayTask, mtGC> MarkSweep::_objarray_stack;
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp Wed May 15 11:05:09 2013 +0200
@@ -113,7 +113,7 @@
//
protected:
// Total invocations of a MarkSweep collection
- static unsigned int _total_invocations;
+ static uint _total_invocations;
// Traversal stacks used during phase1
static Stack<oop, mtGC> _marking_stack;
@@ -147,7 +147,7 @@
static AdjustKlassClosure adjust_klass_closure;
// Accessors
- static unsigned int total_invocations() { return _total_invocations; }
+ static uint total_invocations() { return _total_invocations; }
// Reference Processing
static ReferenceProcessor* const ref_processor() { return _ref_processor; }
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Wed May 15 11:05:09 2013 +0200
@@ -752,7 +752,7 @@
// free memory should be here, especially if they are expensive. If this
// attempt fails, an OOM exception will be thrown.
{
- IntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted
+ UIntFlagSetting flag_change(MarkSweepAlwaysCompactCount, 1); // Make sure the heap is fully compacted
gch->do_collection(true /* full */,
true /* clear_all_soft_refs */,
--- a/hotspot/src/share/vm/memory/space.hpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/memory/space.hpp Wed May 15 11:05:09 2013 +0200
@@ -537,9 +537,8 @@
* Occasionally, we want to ensure a full compaction, which is determined \
* by the MarkSweepAlwaysCompactCount parameter. \
*/ \
- int invocations = MarkSweep::total_invocations(); \
- bool skip_dead = (MarkSweepAlwaysCompactCount < 1) \
- ||((invocations % MarkSweepAlwaysCompactCount) != 0); \
+ uint invocations = MarkSweep::total_invocations(); \
+ bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); \
\
size_t allowed_deadspace = 0; \
if (skip_dead) { \
--- a/hotspot/src/share/vm/runtime/arguments.cpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed May 15 11:05:09 2013 +0200
@@ -1901,7 +1901,7 @@
status = false;
}
- status = status && verify_percentage(AdaptiveSizePolicyWeight,
+ status = status && verify_interval(AdaptiveSizePolicyWeight, 0, 100,
"AdaptiveSizePolicyWeight");
status = status && verify_percentage(ThresholdTolerance, "ThresholdTolerance");
status = status && verify_percentage(MinHeapFreeRatio, "MinHeapFreeRatio");
@@ -1961,8 +1961,6 @@
FLAG_SET_DEFAULT(UseGCOverheadLimit, false);
}
- status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
-
status = status && check_gc_consistency();
status = status && check_stack_pages();
@@ -2056,6 +2054,52 @@
status = status && verify_interval(G1ConcRSLogCacheSize, 0, 31,
"G1ConcRSLogCacheSize");
}
+ if (UseConcMarkSweepGC) {
+ status = status && verify_min_value(CMSOldPLABNumRefills, 1, "CMSOldPLABNumRefills");
+ status = status && verify_min_value(CMSOldPLABToleranceFactor, 1, "CMSOldPLABToleranceFactor");
+ status = status && verify_min_value(CMSOldPLABMax, 1, "CMSOldPLABMax");
+ status = status && verify_interval(CMSOldPLABMin, 1, CMSOldPLABMax, "CMSOldPLABMin");
+
+ status = status && verify_min_value(CMSYoungGenPerWorker, 1, "CMSYoungGenPerWorker");
+
+ status = status && verify_min_value(CMSSamplingGrain, 1, "CMSSamplingGrain");
+ status = status && verify_interval(CMS_SweepWeight, 0, 100, "CMS_SweepWeight");
+ status = status && verify_interval(CMS_FLSWeight, 0, 100, "CMS_FLSWeight");
+
+ status = status && verify_interval(FLSCoalescePolicy, 0, 4, "FLSCoalescePolicy");
+
+ status = status && verify_min_value(CMSRescanMultiple, 1, "CMSRescanMultiple");
+ status = status && verify_min_value(CMSConcMarkMultiple, 1, "CMSConcMarkMultiple");
+
+ status = status && verify_interval(CMSPrecleanIter, 0, 9, "CMSPrecleanIter");
+ status = status && verify_min_value(CMSPrecleanDenominator, 1, "CMSPrecleanDenominator");
+ status = status && verify_interval(CMSPrecleanNumerator, 0, CMSPrecleanDenominator - 1, "CMSPrecleanNumerator");
+
+ status = status && verify_percentage(CMSBootstrapOccupancy, "CMSBootstrapOccupancy");
+
+ status = status && verify_min_value(CMSPrecleanThreshold, 100, "CMSPrecleanThreshold");
+
+ status = status && verify_percentage(CMSScheduleRemarkEdenPenetration, "CMSScheduleRemarkEdenPenetration");
+ status = status && verify_min_value(CMSScheduleRemarkSamplingRatio, 1, "CMSScheduleRemarkSamplingRatio");
+ status = status && verify_min_value(CMSBitMapYieldQuantum, 1, "CMSBitMapYieldQuantum");
+ status = status && verify_percentage(CMSTriggerRatio, "CMSTriggerRatio");
+ status = status && verify_percentage(CMSIsTooFullPercentage, "CMSIsTooFullPercentage");
+ }
+
+ if (UseParallelGC || UseParallelOldGC) {
+ status = status && verify_interval(ParallelOldDeadWoodLimiterMean, 0, 100, "ParallelOldDeadWoodLimiterMean");
+ status = status && verify_interval(ParallelOldDeadWoodLimiterStdDev, 0, 100, "ParallelOldDeadWoodLimiterStdDev");
+
+ status = status && verify_percentage(YoungGenerationSizeIncrement, "YoungGenerationSizeIncrement");
+ status = status && verify_percentage(TenuredGenerationSizeIncrement, "TenuredGenerationSizeIncrement");
+
+ status = status && verify_min_value(YoungGenerationSizeSupplementDecay, 1, "YoungGenerationSizeSupplementDecay");
+ status = status && verify_min_value(TenuredGenerationSizeSupplementDecay, 1, "TenuredGenerationSizeSupplementDecay");
+
+ status = status && verify_min_value(ParGCCardsPerStrideChunk, 1, "ParGCCardsPerStrideChunk");
+
+ status = status && verify_min_value(ParallelOldGCSplitInterval, 0, "ParallelOldGCSplitInterval");
+ }
#endif // INCLUDE_ALL_GCS
status = status && verify_interval(RefDiscoveryPolicy,
@@ -2075,7 +2119,42 @@
status = status && verify_interval(MarkStackSizeMax,
1, (max_jint - 1), "MarkStackSizeMax");
-
+ status = status && verify_interval(NUMAChunkResizeWeight, 0, 100, "NUMAChunkResizeWeight");
+
+ status = status && verify_min_value(LogEventsBufferEntries, 1, "LogEventsBufferEntries");
+
+ status = status && verify_min_value(HeapSizePerGCThread, (uintx) os::vm_page_size(), "HeapSizePerGCThread");
+
+ status = status && verify_min_value(GCTaskTimeStampEntries, 1, "GCTaskTimeStampEntries");
+
+ status = status && verify_percentage(ParallelGCBufferWastePct, "ParallelGCBufferWastePct");
+ status = status && verify_interval(TargetPLABWastePct, 1, 100, "TargetPLABWastePct");
+
+ status = status && verify_min_value(ParGCStridesPerThread, 1, "ParGCStridesPerThread");
+
+ status = status && verify_min_value(MinRAMFraction, 1, "MinRAMFraction");
+ status = status && verify_min_value(InitialRAMFraction, 1, "InitialRAMFraction");
+ status = status && verify_min_value(MaxRAMFraction, 1, "MaxRAMFraction");
+ status = status && verify_min_value(DefaultMaxRAMFraction, 1, "DefaultMaxRAMFraction");
+
+ status = status && verify_interval(AdaptiveTimeWeight, 0, 100, "AdaptiveTimeWeight");
+ status = status && verify_min_value(AdaptiveSizeDecrementScaleFactor, 1, "AdaptiveSizeDecrementScaleFactor");
+
+ status = status && verify_interval(TLABAllocationWeight, 0, 100, "TLABAllocationWeight");
+ status = status && verify_min_value(MinTLABSize, 1, "MinTLABSize");
+ status = status && verify_min_value(TLABRefillWasteFraction, 1, "TLABRefillWasteFraction");
+
+ status = status && verify_percentage(YoungGenerationSizeSupplement, "YoungGenerationSizeSupplement");
+ status = status && verify_percentage(TenuredGenerationSizeSupplement, "TenuredGenerationSizeSupplement");
+
+ // the "age" field in the oop header is 4 bits; do not want to pull in markOop.hpp
+ // just for that, so hardcode here.
+ status = status && verify_interval(MaxTenuringThreshold, 0, 15, "MaxTenuringThreshold");
+ status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "MaxTenuringThreshold");
+ status = status && verify_percentage(TargetSurvivorRatio, "TargetSurvivorRatio");
+ status = status && verify_percentage(MarkSweepDeadRatio, "MarkSweepDeadRatio");
+
+ status = status && verify_min_value(MarkSweepAlwaysCompactCount, 1, "MarkSweepAlwaysCompactCount");
#ifdef SPARC
if (UseConcMarkSweepGC || UseG1GC) {
// Issue a stern warning if the user has explicitly set
--- a/hotspot/src/share/vm/runtime/globals.hpp Tue May 14 17:08:31 2013 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed May 15 11:05:09 2013 +0200
@@ -286,12 +286,12 @@
};
-class IntFlagSetting {
- intx val;
- intx* flag;
+class UIntFlagSetting {
+ uintx val;
+ uintx* flag;
public:
- IntFlagSetting(intx& fl, intx newValue) { flag = &fl; val = fl; fl = newValue; }
- ~IntFlagSetting() { *flag = val; }
+ UIntFlagSetting(uintx& fl, uintx newValue) { flag = &fl; val = fl; fl = newValue; }
+ ~UIntFlagSetting() { *flag = val; }
};
@@ -513,12 +513,12 @@
product(bool, ForceNUMA, false, \
"Force NUMA optimizations on single-node/UMA systems") \
\
- product(intx, NUMAChunkResizeWeight, 20, \
- "Percentage (0-100) used to weight the current sample when " \
+ product(uintx, NUMAChunkResizeWeight, 20, \
+ "Percentage (0-100) used to weigh the current sample when " \
"computing exponentially decaying average for " \
"AdaptiveNUMAChunkSizing") \
\
- product(intx, NUMASpaceResizeRate, 1*G, \
+ product(uintx, NUMASpaceResizeRate, 1*G, \
"Do not reallocate more that this amount per collection") \
\
product(bool, UseAdaptiveNUMAChunkSizing, true, \
@@ -527,7 +527,7 @@
product(bool, NUMAStats, false, \
"Print NUMA stats in detailed heap information") \
\
- product(intx, NUMAPageScanRate, 256, \
+ product(uintx, NUMAPageScanRate, 256, \
"Maximum number of pages to include in the page scan procedure") \
\
product_pd(bool, NeedsDeoptSuspend, \
@@ -715,7 +715,7 @@
diagnostic(bool, LogEvents, true, \
"Enable the various ring buffer event logs") \
\
- diagnostic(intx, LogEventsBufferEntries, 10, \
+ diagnostic(uintx, LogEventsBufferEntries, 10, \
"Enable the various ring buffer event logs") \
\
product(bool, BytecodeVerificationRemote, true, \
@@ -1432,16 +1432,17 @@
product(bool, ParallelGCVerbose, false, \
"Verbose output for parallel GC.") \
\
- product(intx, ParallelGCBufferWastePct, 10, \
- "wasted fraction of parallel allocation buffer.") \
+ product(uintx, ParallelGCBufferWastePct, 10, \
+ "Wasted fraction of parallel allocation buffer.") \
\
diagnostic(bool, ParallelGCRetainPLAB, false, \
"Retain parallel allocation buffers across scavenges; " \
" -- disabled because this currently conflicts with " \
" parallel card scanning under certain conditions ") \
\
- product(intx, TargetPLABWastePct, 10, \
- "target wasted space in last buffer as pct of overall allocation")\
+ product(uintx, TargetPLABWastePct, 10, \
+ "Target wasted space in last buffer as percent of overall " \
+ "allocation") \
\
product(uintx, PLABWeight, 75, \
"Percentage (0-100) used to weight the current sample when" \
@@ -1519,7 +1520,7 @@
product(bool, AlwaysPreTouch, false, \
"It forces all freshly committed pages to be pre-touched.") \
\
- product_pd(intx, CMSYoungGenPerWorker, \
+ product_pd(uintx, CMSYoungGenPerWorker, \
"The maximum size of young gen chosen by default per GC worker " \
"thread available") \
\
@@ -1837,7 +1838,7 @@
product(bool, UseCMSInitiatingOccupancyOnly, false, \
"Only use occupancy as a crierion for starting a CMS collection") \
\
- product(intx, CMSIsTooFullPercentage, 98, \
+ product(uintx, CMSIsTooFullPercentage, 98, \
"An absolute ceiling above which CMS will always consider the " \
"unloading of classes when class unloading is enabled") \
\
@@ -1876,7 +1877,7 @@
develop(uintx, PromotionFailureALotInterval, 5, \
"Total collections between promotion failures alot") \
\
- experimental(intx, WorkStealingSleepMillis, 1, \
+ experimental(uintx, WorkStealingSleepMillis, 1, \
"Sleep time when sleep is used for yields") \
\
experimental(uintx, WorkStealingYieldsBeforeSleep, 5000, \
@@ -2020,7 +2021,7 @@
"Number of collections before the adaptive sizing is started") \
\
product(uintx, AdaptiveSizePolicyOutputInterval, 0, \
- "Collecton interval for printing information; zero => never") \
+ "Collection interval for printing information; zero means never") \
\
product(bool, UseAdaptiveSizePolicyFootprintGoal, true, \
"Use adaptive minimum footprint as a goal") \
@@ -3049,7 +3050,7 @@
product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \
"Max expansion of Metaspace without full GC (in bytes)") \
\
- product(intx, QueuedAllocationWarningCount, 0, \
+ product(uintx, QueuedAllocationWarningCount, 0, \
"Number of times an allocation that queues behind a GC " \
"will retry before printing a warning") \
\
@@ -3077,7 +3078,7 @@
"either completely full or completely empty. Par compact also" \
"has a smaller default value; see arguments.cpp.") \
\
- product(intx, MarkSweepAlwaysCompactCount, 4, \
+ product(uintx, MarkSweepAlwaysCompactCount, 4, \
"How often should we fully compact the heap (ignoring the dead " \
"space parameters)") \
\