src/hotspot/share/gc/cms/commandLineFlagConstraintsCMS.cpp
changeset 49857 31e07291ae29
parent 49856 5f63af8f9d7f
child 49858 56923ee4f07e
equal deleted inserted replaced
49856:5f63af8f9d7f 49857:31e07291ae29
     1 /*
       
     2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "gc/cms/commandLineFlagConstraintsCMS.hpp"
       
    27 #include "gc/cms/concurrentMarkSweepGeneration.inline.hpp"
       
    28 #include "gc/shared/cardTableRS.hpp"
       
    29 #include "gc/shared/collectedHeap.hpp"
       
    30 #include "gc/shared/genCollectedHeap.hpp"
       
    31 #include "gc/shared/commandLineFlagConstraintsGC.hpp"
       
    32 #include "memory/universe.hpp"
       
    33 #include "runtime/commandLineFlagRangeList.hpp"
       
    34 #include "runtime/globals_extension.hpp"
       
    35 #include "utilities/globalDefinitions.hpp"
       
    36 
       
    37 static Flag::Error ParallelGCThreadsAndCMSWorkQueueDrainThreshold(uint threads, uintx threshold, bool verbose) {
       
    38   // CMSWorkQueueDrainThreshold is verified to be less than max_juint
       
    39   if (UseConcMarkSweepGC && (threads > (uint)(max_jint / (uint)threshold))) {
       
    40     CommandLineError::print(verbose,
       
    41                             "ParallelGCThreads (" UINT32_FORMAT ") or CMSWorkQueueDrainThreshold ("
       
    42                             UINTX_FORMAT ") is too large\n",
       
    43                             threads, threshold);
       
    44     return Flag::VIOLATES_CONSTRAINT;
       
    45   }
       
    46   return Flag::SUCCESS;
       
    47 }
       
    48 
       
    49 Flag::Error ParallelGCThreadsConstraintFuncCMS(uint value, bool verbose) {
       
    50   // To avoid overflow at ParScanClosure::do_oop_work.
       
    51   if (UseConcMarkSweepGC && (value > (max_jint / 10))) {
       
    52     CommandLineError::print(verbose,
       
    53                             "ParallelGCThreads (" UINT32_FORMAT ") must be "
       
    54                             "less than or equal to " UINT32_FORMAT " for CMS GC\n",
       
    55                             value, (max_jint / 10));
       
    56     return Flag::VIOLATES_CONSTRAINT;
       
    57   }
       
    58   return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(value, CMSWorkQueueDrainThreshold, verbose);
       
    59 }
       
    60 Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose) {
       
    61   if (UseConcMarkSweepGC && (value > ((uintx)max_jint / (uintx)ParallelGCThreads))) {
       
    62     CommandLineError::print(verbose,
       
    63                             "ParGCStridesPerThread (" UINTX_FORMAT ") must be "
       
    64                             "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
       
    65                             value, ((uintx)max_jint / (uintx)ParallelGCThreads));
       
    66     return Flag::VIOLATES_CONSTRAINT;
       
    67   }
       
    68   return Flag::SUCCESS;
       
    69 }
       
    70 
       
    71 Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose) {
       
    72   if (UseConcMarkSweepGC) {
       
    73     // ParGCCardsPerStrideChunk should be compared with card table size.
       
    74     size_t heap_size = Universe::heap()->reserved_region().word_size();
       
    75     CardTableRS* ct = GenCollectedHeap::heap()->rem_set();
       
    76     size_t card_table_size = ct->cards_required(heap_size) - 1; // Valid card table size
       
    77 
       
    78     if ((size_t)value > card_table_size) {
       
    79       CommandLineError::print(verbose,
       
    80                               "ParGCCardsPerStrideChunk (" INTX_FORMAT ") is too large for the heap size and "
       
    81                               "must be less than or equal to card table size (" SIZE_FORMAT ")\n",
       
    82                               value, card_table_size);
       
    83       return Flag::VIOLATES_CONSTRAINT;
       
    84     }
       
    85 
       
    86     // ParGCCardsPerStrideChunk is used with n_strides(ParallelGCThreads*ParGCStridesPerThread)
       
    87     // from CardTableRS::process_stride(). Note that ParGCStridesPerThread is already checked
       
    88     // not to make an overflow with ParallelGCThreads from its constraint function.
       
    89     uintx n_strides = ParallelGCThreads * ParGCStridesPerThread;
       
    90     uintx ergo_max = max_uintx / n_strides;
       
    91     if ((uintx)value > ergo_max) {
       
    92       CommandLineError::print(verbose,
       
    93                               "ParGCCardsPerStrideChunk (" INTX_FORMAT ") must be "
       
    94                               "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
       
    95                               value, ergo_max);
       
    96       return Flag::VIOLATES_CONSTRAINT;
       
    97     }
       
    98   }
       
    99   return Flag::SUCCESS;
       
   100 }
       
   101 
       
   102 Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose) {
       
   103   Flag::Error status = Flag::SUCCESS;
       
   104 
       
   105   if (UseConcMarkSweepGC) {
       
   106     if (value > CMSOldPLABMax) {
       
   107       CommandLineError::print(verbose,
       
   108                               "CMSOldPLABMin (" SIZE_FORMAT ") must be "
       
   109                               "less than or equal to CMSOldPLABMax (" SIZE_FORMAT ")\n",
       
   110                               value, CMSOldPLABMax);
       
   111       return Flag::VIOLATES_CONSTRAINT;
       
   112     }
       
   113     status = MaxPLABSizeBounds("CMSOldPLABMin", value, verbose);
       
   114   }
       
   115   return status;
       
   116 }
       
   117 
       
   118 Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose) {
       
   119   Flag::Error status = Flag::SUCCESS;
       
   120 
       
   121   if (UseConcMarkSweepGC) {
       
   122     status = MaxPLABSizeBounds("CMSOldPLABMax", value, verbose);
       
   123   }
       
   124   return status;
       
   125 }
       
   126 
       
   127 static Flag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) {
       
   128   if (UseConcMarkSweepGC) {
       
   129     ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen();
       
   130     const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size();
       
   131     if (value > ergo_max) {
       
   132       CommandLineError::print(verbose,
       
   133                               "%s (" SIZE_FORMAT ") must be "
       
   134                               "less than or equal to ergonomic maximum (" SIZE_FORMAT ") "
       
   135                               "which is based on the maximum size of the old generation of the Java heap\n",
       
   136                               name, value, ergo_max);
       
   137       return Flag::VIOLATES_CONSTRAINT;
       
   138     }
       
   139   }
       
   140 
       
   141   return Flag::SUCCESS;
       
   142 }
       
   143 
       
   144 Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose) {
       
   145   Flag::Error status = CMSReservedAreaConstraintFunc("CMSRescanMultiple", value, verbose);
       
   146 
       
   147   if (status == Flag::SUCCESS && UseConcMarkSweepGC) {
       
   148     // CMSParRemarkTask::do_dirty_card_rescan_tasks requires CompactibleFreeListSpace::rescan_task_size()
       
   149     // to be aligned to CardTable::card_size * BitsPerWord.
       
   150     // Note that rescan_task_size() will be aligned if CMSRescanMultiple is a multiple of 'HeapWordSize'
       
   151     // because rescan_task_size() is CardTable::card_size / HeapWordSize * BitsPerWord.
       
   152     if (value % HeapWordSize != 0) {
       
   153       CommandLineError::print(verbose,
       
   154                               "CMSRescanMultiple (" SIZE_FORMAT ") must be "
       
   155                               "a multiple of " SIZE_FORMAT "\n",
       
   156                               value, HeapWordSize);
       
   157       status = Flag::VIOLATES_CONSTRAINT;
       
   158     }
       
   159   }
       
   160 
       
   161   return status;
       
   162 }
       
   163 
       
   164 Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose) {
       
   165   return CMSReservedAreaConstraintFunc("CMSConcMarkMultiple", value, verbose);
       
   166 }
       
   167 
       
   168 Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) {
       
   169   if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) {
       
   170     CommandLineError::print(verbose,
       
   171                             "CMSPrecleanDenominator (" UINTX_FORMAT ") must be "
       
   172                             "strickly greater than CMSPrecleanNumerator (" UINTX_FORMAT ")\n",
       
   173                             value, CMSPrecleanNumerator);
       
   174     return Flag::VIOLATES_CONSTRAINT;
       
   175   }
       
   176   return Flag::SUCCESS;
       
   177 }
       
   178 
       
   179 Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose) {
       
   180   if (UseConcMarkSweepGC && (value >= CMSPrecleanDenominator)) {
       
   181     CommandLineError::print(verbose,
       
   182                             "CMSPrecleanNumerator (" UINTX_FORMAT ") must be "
       
   183                             "less than CMSPrecleanDenominator (" UINTX_FORMAT ")\n",
       
   184                             value, CMSPrecleanDenominator);
       
   185     return Flag::VIOLATES_CONSTRAINT;
       
   186   }
       
   187   return Flag::SUCCESS;
       
   188 }
       
   189 
       
   190 Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose) {
       
   191   if (UseConcMarkSweepGC) {
       
   192     size_t max_capacity = GenCollectedHeap::heap()->young_gen()->max_capacity();
       
   193     if (value > max_uintx - max_capacity) {
       
   194     CommandLineError::print(verbose,
       
   195                             "CMSSamplingGrain (" UINTX_FORMAT ") must be "
       
   196                             "less than or equal to ergonomic maximum (" SIZE_FORMAT ")\n",
       
   197                             value, max_uintx - max_capacity);
       
   198     return Flag::VIOLATES_CONSTRAINT;
       
   199     }
       
   200   }
       
   201   return Flag::SUCCESS;
       
   202 }
       
   203 
       
   204 Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose) {
       
   205   if (UseConcMarkSweepGC) {
       
   206     return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(ParallelGCThreads, value, verbose);
       
   207   }
       
   208   return Flag::SUCCESS;
       
   209 }
       
   210 
       
   211 Flag::Error CMSBitMapYieldQuantumConstraintFunc(size_t value, bool verbose) {
       
   212   // Skip for current default value.
       
   213   if (UseConcMarkSweepGC && FLAG_IS_CMDLINE(CMSBitMapYieldQuantum)) {
       
   214     // CMSBitMapYieldQuantum should be compared with mark bitmap size.
       
   215     ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen();
       
   216     size_t bitmap_size = cms->collector()->markBitMap()->sizeInWords();
       
   217 
       
   218     if (value > bitmap_size) {
       
   219       CommandLineError::print(verbose,
       
   220                               "CMSBitMapYieldQuantum (" SIZE_FORMAT ") must "
       
   221                               "be less than or equal to bitmap size (" SIZE_FORMAT ") "
       
   222                               "whose size corresponds to the size of old generation of the Java heap\n",
       
   223                               value, bitmap_size);
       
   224       return Flag::VIOLATES_CONSTRAINT;
       
   225     }
       
   226   }
       
   227   return Flag::SUCCESS;
       
   228 }
       
   229 
       
   230 Flag::Error OldPLABSizeConstraintFuncCMS(size_t value, bool verbose) {
       
   231   if (value == 0) {
       
   232     CommandLineError::print(verbose,
       
   233                             "OldPLABSize (" SIZE_FORMAT ") must be greater than 0",
       
   234                             value);
       
   235     return Flag::VIOLATES_CONSTRAINT;
       
   236   }
       
   237   // For CMS, OldPLABSize is the number of free blocks of a given size that are used when
       
   238   // replenishing the local per-worker free list caches.
       
   239   // For more details, please refer to Arguments::set_cms_and_parnew_gc_flags().
       
   240   return MaxPLABSizeBounds("OldPLABSize", value, verbose);
       
   241 }