--- old/src/share/vm/runtime/arguments.cpp 2015-08-20 09:32:01.033084091 -0700 +++ new/src/share/vm/runtime/arguments.cpp 2015-08-20 09:32:00.917084095 -0700 @@ -581,9 +581,10 @@ } static bool set_fp_numeric_flag(char* name, char* value, Flag::Flags origin) { + char* end; errno = 0; - double v = strtod(value, NULL); - if (errno == ERANGE) { + double v = strtod(value, &end); + if (errno != 0 || *end != 0) { return false; } @@ -719,7 +720,7 @@ #define SIGNED_FP_NUMBER_RANGE "[-0123456789.eE+]" #define SIGNED_NUMBER_RANGE "[-0123456789]" -#define NUMBER_RANGE "[0123456789eE+]" +#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) { --- old/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp 2015-08-20 09:32:01.761084065 -0700 +++ new/src/share/vm/runtime/commandLineFlagConstraintsGC.cpp 2015-08-20 09:32:01.657084069 -0700 @@ -45,20 +45,25 @@ #include "opto/c2_globals.hpp" #endif // COMPILER2 -static Flag::Error ParallelGCThreadsAndCMSWorkQueueDrainThreshold(bool verbose) { +#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 && (ParallelGCThreads > (uint)(max_jint / (uint)CMSWorkQueueDrainThreshold))) { + if (UseConcMarkSweepGC && (threads > (uint)(max_jint / (uint)threshold))) { CommandLineError::print(verbose, "ParallelGCThreads (" UINT32_FORMAT ") or CMSWorkQueueDrainThreshold (" UINTX_FORMAT ") is too large\n", - ParallelGCThreads, CMSWorkQueueDrainThreshold); + 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)) { @@ -68,11 +73,6 @@ value, max_jint); return Flag::VIOLATES_CONSTRAINT; } - // G1, CMS and Parallel GC modes disallows ParallelGCThreads=0 - if ((UseG1GC || UseConcMarkSweepGC || UseParallelGC) && (value == 0)) { - CommandLineError::print(verbose, "ParallelGCThreads cannot be zero\n"); - return Flag::VIOLATES_CONSTRAINT; - } // To avoid overflow at ParScanClosure::do_oop_work. if (UseConcMarkSweepGC && (value > max_jint / 10)) { CommandLineError::print(verbose, @@ -81,13 +81,15 @@ value, max_jint / 10); return Flag::VIOLATES_CONSTRAINT; } - - return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(verbose); + 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, @@ -95,9 +97,9 @@ "ParallelGCThreads (" UINT32_FORMAT ")\n", value, ParallelGCThreads); return Flag::VIOLATES_CONSTRAINT; - } else { - return Flag::SUCCESS; } +#endif + return Flag::SUCCESS; } static Flag::Error MinPLABSizeBounds(const char* name, size_t value, bool verbose) { @@ -140,6 +142,9 @@ } 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, @@ -150,10 +155,12 @@ // 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(). - return MaxPLABSizeBounds("OldPLABSize", value, verbose); + status = MaxPLABSizeBounds("OldPLABSize", value, verbose); } else { - return MinMaxPLABSizeBounds("OldPLABSize", value, verbose); + status = MinMaxPLABSizeBounds("OldPLABSize", value, verbose); } +#endif + return status; } Flag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose) { @@ -180,13 +187,12 @@ } } -static Flag::Error CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(bool verbose) { - if ((SoftRefLRUPolicyMSPerMB > 0) && - (MaxHeapSize / M > max_uintx / SoftRefLRUPolicyMSPerMB)) { +static Flag::Error CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(size_t maxHeap, intx softRef, bool verbose) { + if ((softRef > 0) && (maxHeap / M > max_uintx / softRef)) { CommandLineError::print(verbose, "MaxHeapSize (" SIZE_FORMAT ") or SoftRefLRUPolicyMSPerMB " "(" INTX_FORMAT ") is too large\n", - MaxHeapSize, SoftRefLRUPolicyMSPerMB); + maxHeap, softRef); return Flag::VIOLATES_CONSTRAINT; } else { return Flag::SUCCESS; @@ -194,7 +200,7 @@ } Flag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose) { - return CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(verbose); + return CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(MaxHeapSize, value, verbose); } Flag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) { @@ -222,23 +228,21 @@ } Flag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose) { +#if INCLUDE_ALL_GCS // InitialTenuringThreshold is only used for ParallelGC. - if (!UseParallelGC) { - return Flag::SUCCESS; - } - - if (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; - } else { - return Flag::SUCCESS; + 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 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)) { @@ -248,6 +252,7 @@ value, InitialTenuringThreshold); return Flag::VIOLATES_CONSTRAINT; } +#endif // MaxTenuringThreshold=0 means NeverTenure=false && AlwaysTenure=true if ((value == 0) && (NeverTenure || !AlwaysTenure)) { @@ -354,107 +359,117 @@ #endif // INCLUDE_ALL_GCS Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose) { - if (!UseConcMarkSweepGC) return Flag::SUCCESS; - - if (value > max_jint / ParallelGCThreads) { +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC && (value > max_jint / ParallelGCThreads)) { CommandLineError::print(verbose, "ParGCStridesPerThread (" UINTX_FORMAT ") must be " "less than or equal to ergonomic maximum (" INT32_FORMAT ")\n", value, max_jint / ParallelGCThreads); return Flag::VIOLATES_CONSTRAINT; - } else { - return Flag::SUCCESS; } +#endif + return Flag::SUCCESS; } Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose) { - if (!UseConcMarkSweepGC) return Flag::SUCCESS; + Flag::Error status = Flag::SUCCESS; - 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; +#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); } - - return MaxPLABSizeBounds("CMSOldPLABMin", value, verbose); +#endif + return status; } Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose) { - if (!UseConcMarkSweepGC) return Flag::SUCCESS; + Flag::Error status = Flag::SUCCESS; - return MaxPLABSizeBounds("CMSOldPLABMax", value, verbose); +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC) { + status = MaxPLABSizeBounds("CMSOldPLABMax", value, verbose); + } +#endif + return status; } Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) { - if (!UseConcMarkSweepGC) return Flag::SUCCESS; - - 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; - } else { - return Flag::SUCCESS; } +#endif + return Flag::SUCCESS; } Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose) { - if (!UseConcMarkSweepGC) return Flag::SUCCESS; - - if (value >= CMSPrecleanDenominator) { +#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; - } else { - return Flag::SUCCESS; } +#endif + return Flag::SUCCESS; } Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose) { - if (!UseConcMarkSweepGC) return Flag::SUCCESS; - - return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(verbose); +#if INCLUDE_ALL_GCS + if (UseConcMarkSweepGC) { + return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(ParallelGCThreads, value, verbose); + } +#endif + return Flag::SUCCESS; } Flag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose) { - if (!UseG1GC) return Flag::SUCCESS; - - if (FLAG_IS_CMDLINE(MaxGCPauseMillis) && (value >= GCPauseIntervalMillis)) { +#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; - } else { - return Flag::SUCCESS; } +#endif + + return Flag::SUCCESS; } Flag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose) { - if (!UseG1GC) return Flag::SUCCESS; - - 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; +#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; } @@ -503,7 +518,7 @@ Flag::Error status = MaxSizeForHeapAlignment("MaxHeapSize", value, verbose); if (status == Flag::SUCCESS) { - status = CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(verbose); + status = CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(value, SoftRefLRUPolicyMSPerMB, verbose); } return status; } @@ -523,7 +538,6 @@ } #endif // INCLUDE_ALL_GCS #endif // _LP64 - return Flag::SUCCESS; } --- old/src/share/vm/runtime/globals.hpp 2015-08-20 09:32:02.417084042 -0700 +++ new/src/share/vm/runtime/globals.hpp 2015-08-20 09:32:02.301084046 -0700 @@ -1849,15 +1849,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") \ - range(0, MarkStackSizeMax) \ - \ /* 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") \ + range(0, MarkStackSizeMax) \ + \ notproduct(bool, CMSMarkStackOverflowALot, false, \ "Simulate frequent marking stack / work queue overflow") \ \ --- old/test/gc/arguments/TestG1ConcMarkStepDurationMillis.java 2015-08-20 09:32:03.081084019 -0700 +++ new/test/gc/arguments/TestG1ConcMarkStepDurationMillis.java 2015-08-20 09:32:02.977084023 -0700 @@ -36,27 +36,37 @@ public class TestG1ConcMarkStepDurationMillis { - static final int EXPECT_TO_PASS = 0; - static final int EXPECT_TO_FAIL = 1; - - static final String DOUBLE_1 = "1.0"; - static final String DOUBLE_MAX = "1.79e+308"; - - static final String PO_DOUBLE_INF = "1.79e+309"; - static final String DOUBLE_N_1 = "-1.0"; - static final String NE_DOUBLE_INF = "-1.79e+309"; - static final String DOUBLE_NAN = "abe+309"; + 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, EXPECT_TO_PASS); - runG1ConcMarkStepDurationMillisTest(DOUBLE_MAX, EXPECT_TO_PASS); + runG1ConcMarkStepDurationMillisTest(DOUBLE_1, PASS); + runG1ConcMarkStepDurationMillisTest(DOUBLE_MAX, PASS); - // Fail cases - runG1ConcMarkStepDurationMillisTest(PO_DOUBLE_INF, EXPECT_TO_FAIL); - runG1ConcMarkStepDurationMillisTest(DOUBLE_N_1, EXPECT_TO_FAIL); - runG1ConcMarkStepDurationMillisTest(NE_DOUBLE_INF, EXPECT_TO_FAIL); - runG1ConcMarkStepDurationMillisTest(DOUBLE_NAN, EXPECT_TO_FAIL); + // 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 { @@ -67,12 +77,14 @@ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()])); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(expectedResult); + output.shouldHaveExitValue(expectedResult == PASS ? 0 : 1); String stdout = output.getStdout(); - if (expectedResult == 0) { + if (expectedResult == PASS) { checkG1ConcMarkStepDurationMillisConsistency(stdout, expectedValue); - } else { + } else if (expectedResult == FAIL_IMPROPER_VALUE) { output.shouldContain("Improperly specified VM option"); + } else if (expectedResult == FAIL_OUT_RANGE) { + output.shouldContain("outside the allowed range"); } }