src/hotspot/share/gc/cms/jvmFlagConstraintsCMS.cpp
branchaefimov-dns-client-branch
changeset 59099 fcdb8e7ead8f
parent 58984 15e026239a6c
parent 59075 355f4f42dda5
child 59100 b92aac38b046
equal deleted inserted replaced
58984:15e026239a6c 59099:fcdb8e7ead8f
     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/jvmFlagConstraintsCMS.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/jvmFlagConstraintsGC.hpp"
       
    32 #include "memory/universe.hpp"
       
    33 #include "runtime/globals_extension.hpp"
       
    34 #include "utilities/globalDefinitions.hpp"
       
    35 
       
    36 static JVMFlag::Error ParallelGCThreadsAndCMSWorkQueueDrainThreshold(uint threads, uintx threshold, bool verbose) {
       
    37   // CMSWorkQueueDrainThreshold is verified to be less than max_juint
       
    38   if (UseConcMarkSweepGC && (threads > (uint)(max_jint / (uint)threshold))) {
       
    39     JVMFlag::printError(verbose,
       
    40                         "ParallelGCThreads (" UINT32_FORMAT ") or CMSWorkQueueDrainThreshold ("
       
    41                         UINTX_FORMAT ") is too large\n",
       
    42                         threads, threshold);
       
    43     return JVMFlag::VIOLATES_CONSTRAINT;
       
    44   }
       
    45   return JVMFlag::SUCCESS;
       
    46 }
       
    47 
       
    48 JVMFlag::Error ParallelGCThreadsConstraintFuncCMS(uint value, bool verbose) {
       
    49   // To avoid overflow at ParScanClosure::do_oop_work.
       
    50   if (UseConcMarkSweepGC && (value > (max_jint / 10))) {
       
    51     JVMFlag::printError(verbose,
       
    52                         "ParallelGCThreads (" UINT32_FORMAT ") must be "
       
    53                         "less than or equal to " UINT32_FORMAT " for CMS GC\n",
       
    54                         value, (max_jint / 10));
       
    55     return JVMFlag::VIOLATES_CONSTRAINT;
       
    56   }
       
    57   return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(value, CMSWorkQueueDrainThreshold, verbose);
       
    58 }
       
    59 JVMFlag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose) {
       
    60   if (UseConcMarkSweepGC && (value > ((uintx)max_jint / (uintx)ParallelGCThreads))) {
       
    61     JVMFlag::printError(verbose,
       
    62                         "ParGCStridesPerThread (" UINTX_FORMAT ") must be "
       
    63                         "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
       
    64                         value, ((uintx)max_jint / (uintx)ParallelGCThreads));
       
    65     return JVMFlag::VIOLATES_CONSTRAINT;
       
    66   }
       
    67   return JVMFlag::SUCCESS;
       
    68 }
       
    69 
       
    70 JVMFlag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose) {
       
    71   if (UseConcMarkSweepGC) {
       
    72     // ParGCCardsPerStrideChunk should be compared with card table size.
       
    73     size_t heap_size = CMSHeap::heap()->reserved_region().word_size();
       
    74     CardTableRS* ct = GenCollectedHeap::heap()->rem_set();
       
    75     size_t card_table_size = ct->cards_required(heap_size) - 1; // Valid card table size
       
    76 
       
    77     if ((size_t)value > card_table_size) {
       
    78       JVMFlag::printError(verbose,
       
    79                           "ParGCCardsPerStrideChunk (" INTX_FORMAT ") is too large for the heap size and "
       
    80                           "must be less than or equal to card table size (" SIZE_FORMAT ")\n",
       
    81                           value, card_table_size);
       
    82       return JVMFlag::VIOLATES_CONSTRAINT;
       
    83     }
       
    84 
       
    85     // ParGCCardsPerStrideChunk is used with n_strides(ParallelGCThreads*ParGCStridesPerThread)
       
    86     // from CardTableRS::process_stride(). Note that ParGCStridesPerThread is already checked
       
    87     // not to make an overflow with ParallelGCThreads from its constraint function.
       
    88     uintx n_strides = ParallelGCThreads * ParGCStridesPerThread;
       
    89     uintx ergo_max = max_uintx / n_strides;
       
    90     if ((uintx)value > ergo_max) {
       
    91       JVMFlag::printError(verbose,
       
    92                           "ParGCCardsPerStrideChunk (" INTX_FORMAT ") must be "
       
    93                           "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
       
    94                           value, ergo_max);
       
    95       return JVMFlag::VIOLATES_CONSTRAINT;
       
    96     }
       
    97   }
       
    98   return JVMFlag::SUCCESS;
       
    99 }
       
   100 
       
   101 JVMFlag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose) {
       
   102   JVMFlag::Error status = JVMFlag::SUCCESS;
       
   103 
       
   104   if (UseConcMarkSweepGC) {
       
   105     if (value > CMSOldPLABMax) {
       
   106       JVMFlag::printError(verbose,
       
   107                           "CMSOldPLABMin (" SIZE_FORMAT ") must be "
       
   108                           "less than or equal to CMSOldPLABMax (" SIZE_FORMAT ")\n",
       
   109                           value, CMSOldPLABMax);
       
   110       return JVMFlag::VIOLATES_CONSTRAINT;
       
   111     }
       
   112     status = MaxPLABSizeBounds("CMSOldPLABMin", value, verbose);
       
   113   }
       
   114   return status;
       
   115 }
       
   116 
       
   117 JVMFlag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose) {
       
   118   JVMFlag::Error status = JVMFlag::SUCCESS;
       
   119 
       
   120   if (UseConcMarkSweepGC) {
       
   121     status = MaxPLABSizeBounds("CMSOldPLABMax", value, verbose);
       
   122   }
       
   123   return status;
       
   124 }
       
   125 
       
   126 static JVMFlag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) {
       
   127   if (UseConcMarkSweepGC) {
       
   128     ConcurrentMarkSweepGeneration* cms = CMSHeap::heap()->old_gen();
       
   129     const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size();
       
   130     if (value > ergo_max) {
       
   131       JVMFlag::printError(verbose,
       
   132                           "%s (" SIZE_FORMAT ") must be "
       
   133                           "less than or equal to ergonomic maximum (" SIZE_FORMAT ") "
       
   134                           "which is based on the maximum size of the old generation of the Java heap\n",
       
   135                           name, value, ergo_max);
       
   136       return JVMFlag::VIOLATES_CONSTRAINT;
       
   137     }
       
   138   }
       
   139   return JVMFlag::SUCCESS;
       
   140 }
       
   141 
       
   142 JVMFlag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose) {
       
   143   JVMFlag::Error status = CMSReservedAreaConstraintFunc("CMSRescanMultiple", value, verbose);
       
   144 
       
   145   if (status == JVMFlag::SUCCESS && UseConcMarkSweepGC) {
       
   146     // CMSParRemarkTask::do_dirty_card_rescan_tasks requires CompactibleFreeListSpace::rescan_task_size()
       
   147     // to be aligned to CardTable::card_size * BitsPerWord.
       
   148     // Note that rescan_task_size() will be aligned if CMSRescanMultiple is a multiple of 'HeapWordSize'
       
   149     // because rescan_task_size() is CardTable::card_size / HeapWordSize * BitsPerWord.
       
   150     if (value % HeapWordSize != 0) {
       
   151       JVMFlag::printError(verbose,
       
   152                           "CMSRescanMultiple (" SIZE_FORMAT ") must be "
       
   153                           "a multiple of %d\n",
       
   154                           value, HeapWordSize);
       
   155       status = JVMFlag::VIOLATES_CONSTRAINT;
       
   156     }
       
   157   }
       
   158   return status;
       
   159 }
       
   160 
       
   161 JVMFlag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose) {
       
   162   return CMSReservedAreaConstraintFunc("CMSConcMarkMultiple", value, verbose);
       
   163 }
       
   164 
       
   165 JVMFlag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) {
       
   166   if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) {
       
   167     JVMFlag::printError(verbose,
       
   168                         "CMSPrecleanDenominator (" UINTX_FORMAT ") must be "
       
   169                         "strickly greater than CMSPrecleanNumerator (" UINTX_FORMAT ")\n",
       
   170                         value, CMSPrecleanNumerator);
       
   171     return JVMFlag::VIOLATES_CONSTRAINT;
       
   172   }
       
   173   return JVMFlag::SUCCESS;
       
   174 }
       
   175 
       
   176 JVMFlag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose) {
       
   177   if (UseConcMarkSweepGC && (value >= CMSPrecleanDenominator)) {
       
   178     JVMFlag::printError(verbose,
       
   179                         "CMSPrecleanNumerator (" UINTX_FORMAT ") must be "
       
   180                         "less than CMSPrecleanDenominator (" UINTX_FORMAT ")\n",
       
   181                         value, CMSPrecleanDenominator);
       
   182     return JVMFlag::VIOLATES_CONSTRAINT;
       
   183   }
       
   184   return JVMFlag::SUCCESS;
       
   185 }
       
   186 
       
   187 JVMFlag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose) {
       
   188   if (UseConcMarkSweepGC) {
       
   189     size_t max_capacity = CMSHeap::heap()->young_gen()->max_capacity();
       
   190     if (value > max_uintx - max_capacity) {
       
   191     JVMFlag::printError(verbose,
       
   192                         "CMSSamplingGrain (" UINTX_FORMAT ") must be "
       
   193                         "less than or equal to ergonomic maximum (" SIZE_FORMAT ")\n",
       
   194                         value, max_uintx - max_capacity);
       
   195     return JVMFlag::VIOLATES_CONSTRAINT;
       
   196     }
       
   197   }
       
   198   return JVMFlag::SUCCESS;
       
   199 }
       
   200 
       
   201 JVMFlag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose) {
       
   202   if (UseConcMarkSweepGC) {
       
   203     return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(ParallelGCThreads, value, verbose);
       
   204   }
       
   205   return JVMFlag::SUCCESS;
       
   206 }
       
   207 
       
   208 JVMFlag::Error CMSBitMapYieldQuantumConstraintFunc(size_t value, bool verbose) {
       
   209   // Skip for current default value.
       
   210   if (UseConcMarkSweepGC && FLAG_IS_CMDLINE(CMSBitMapYieldQuantum)) {
       
   211     // CMSBitMapYieldQuantum should be compared with mark bitmap size.
       
   212     ConcurrentMarkSweepGeneration* cms = CMSHeap::heap()->old_gen();
       
   213     size_t bitmap_size = cms->collector()->markBitMap()->sizeInWords();
       
   214 
       
   215     if (value > bitmap_size) {
       
   216       JVMFlag::printError(verbose,
       
   217                           "CMSBitMapYieldQuantum (" SIZE_FORMAT ") must "
       
   218                           "be less than or equal to bitmap size (" SIZE_FORMAT ") "
       
   219                           "whose size corresponds to the size of old generation of the Java heap\n",
       
   220                           value, bitmap_size);
       
   221       return JVMFlag::VIOLATES_CONSTRAINT;
       
   222     }
       
   223   }
       
   224   return JVMFlag::SUCCESS;
       
   225 }
       
   226 
       
   227 JVMFlag::Error OldPLABSizeConstraintFuncCMS(size_t value, bool verbose) {
       
   228   if (value == 0) {
       
   229     JVMFlag::printError(verbose,
       
   230                         "OldPLABSize (" SIZE_FORMAT ") must be greater than 0",
       
   231                         value);
       
   232     return JVMFlag::VIOLATES_CONSTRAINT;
       
   233   }
       
   234   // For CMS, OldPLABSize is the number of free blocks of a given size that are used when
       
   235   // replenishing the local per-worker free list caches.
       
   236   // For more details, please refer to Arguments::set_cms_and_parnew_gc_flags().
       
   237   return MaxPLABSizeBounds("OldPLABSize", value, verbose);
       
   238 }