src/hotspot/share/runtime/flags/jvmFlagRangeList.cpp
changeset 49857 31e07291ae29
parent 49715 947560700a09
equal deleted inserted replaced
49856:5f63af8f9d7f 49857:31e07291ae29
       
     1 /*
       
     2  * Copyright (c) 2015, 2017, 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 "jvm.h"
       
    27 #include "classfile/stringTable.hpp"
       
    28 #include "classfile/symbolTable.hpp"
       
    29 #include "gc/shared/referenceProcessor.hpp"
       
    30 #include "oops/markOop.hpp"
       
    31 #include "runtime/arguments.hpp"
       
    32 #include "runtime/flags/jvmFlag.hpp"
       
    33 #include "runtime/flags/jvmFlagConstraintList.hpp"
       
    34 #include "runtime/flags/jvmFlagRangeList.hpp"
       
    35 #include "runtime/globals_extension.hpp"
       
    36 #include "runtime/os.hpp"
       
    37 #include "runtime/task.hpp"
       
    38 #include "utilities/defaultStream.hpp"
       
    39 #include "utilities/macros.hpp"
       
    40 
       
    41 void CommandLineError::print(bool verbose, const char* msg, ...) {
       
    42   if (verbose) {
       
    43     va_list listPointer;
       
    44     va_start(listPointer, msg);
       
    45     jio_vfprintf(defaultStream::error_stream(), msg, listPointer);
       
    46     va_end(listPointer);
       
    47   }
       
    48 }
       
    49 
       
    50 class JVMFlagRange_int : public JVMFlagRange {
       
    51   int _min;
       
    52   int _max;
       
    53   const int* _ptr;
       
    54 
       
    55 public:
       
    56   // the "name" argument must be a string literal
       
    57   JVMFlagRange_int(const char* name, const int* ptr, int min, int max)
       
    58     : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
       
    59 
       
    60   JVMFlag::Error check(bool verbose = true) {
       
    61     return check_int(*_ptr, verbose);
       
    62   }
       
    63 
       
    64   JVMFlag::Error check_int(int value, bool verbose = true) {
       
    65     if ((value < _min) || (value > _max)) {
       
    66       CommandLineError::print(verbose,
       
    67                               "int %s=%d is outside the allowed range "
       
    68                               "[ %d ... %d ]\n",
       
    69                               name(), value, _min, _max);
       
    70       return JVMFlag::OUT_OF_BOUNDS;
       
    71     } else {
       
    72       return JVMFlag::SUCCESS;
       
    73     }
       
    74   }
       
    75 
       
    76   void print(outputStream* st) {
       
    77     st->print("[ %-25d ... %25d ]", _min, _max);
       
    78   }
       
    79 };
       
    80 
       
    81 class JVMFlagRange_intx : public JVMFlagRange {
       
    82   intx _min;
       
    83   intx _max;
       
    84   const intx* _ptr;
       
    85 public:
       
    86   // the "name" argument must be a string literal
       
    87   JVMFlagRange_intx(const char* name, const intx* ptr, intx min, intx max)
       
    88     : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
       
    89 
       
    90   JVMFlag::Error check(bool verbose = true) {
       
    91     return check_intx(*_ptr, verbose);
       
    92   }
       
    93 
       
    94   JVMFlag::Error check_intx(intx value, bool verbose = true) {
       
    95     if ((value < _min) || (value > _max)) {
       
    96       CommandLineError::print(verbose,
       
    97                               "intx %s=" INTX_FORMAT " is outside the allowed range "
       
    98                               "[ " INTX_FORMAT " ... " INTX_FORMAT " ]\n",
       
    99                               name(), value, _min, _max);
       
   100       return JVMFlag::OUT_OF_BOUNDS;
       
   101     } else {
       
   102       return JVMFlag::SUCCESS;
       
   103     }
       
   104   }
       
   105 
       
   106   void print(outputStream* st) {
       
   107     st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", _min, _max);
       
   108   }
       
   109 };
       
   110 
       
   111 class JVMFlagRange_uint : public JVMFlagRange {
       
   112   uint _min;
       
   113   uint _max;
       
   114   const uint* _ptr;
       
   115 
       
   116 public:
       
   117   // the "name" argument must be a string literal
       
   118   JVMFlagRange_uint(const char* name, const uint* ptr, uint min, uint max)
       
   119     : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
       
   120 
       
   121   JVMFlag::Error check(bool verbose = true) {
       
   122     return check_uint(*_ptr, verbose);
       
   123   }
       
   124 
       
   125   JVMFlag::Error check_uint(uint value, bool verbose = true) {
       
   126     if ((value < _min) || (value > _max)) {
       
   127       CommandLineError::print(verbose,
       
   128                               "uint %s=%u is outside the allowed range "
       
   129                               "[ %u ... %u ]\n",
       
   130                               name(), value, _min, _max);
       
   131       return JVMFlag::OUT_OF_BOUNDS;
       
   132     } else {
       
   133       return JVMFlag::SUCCESS;
       
   134     }
       
   135   }
       
   136 
       
   137   void print(outputStream* st) {
       
   138     st->print("[ %-25u ... %25u ]", _min, _max);
       
   139   }
       
   140 };
       
   141 
       
   142 class JVMFlagRange_uintx : public JVMFlagRange {
       
   143   uintx _min;
       
   144   uintx _max;
       
   145   const uintx* _ptr;
       
   146 
       
   147 public:
       
   148   // the "name" argument must be a string literal
       
   149   JVMFlagRange_uintx(const char* name, const uintx* ptr, uintx min, uintx max)
       
   150     : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
       
   151 
       
   152   JVMFlag::Error check(bool verbose = true) {
       
   153     return check_uintx(*_ptr, verbose);
       
   154   }
       
   155 
       
   156   JVMFlag::Error check_uintx(uintx value, bool verbose = true) {
       
   157     if ((value < _min) || (value > _max)) {
       
   158       CommandLineError::print(verbose,
       
   159                               "uintx %s=" UINTX_FORMAT " is outside the allowed range "
       
   160                               "[ " UINTX_FORMAT " ... " UINTX_FORMAT " ]\n",
       
   161                               name(), value, _min, _max);
       
   162       return JVMFlag::OUT_OF_BOUNDS;
       
   163     } else {
       
   164       return JVMFlag::SUCCESS;
       
   165     }
       
   166   }
       
   167 
       
   168   void print(outputStream* st) {
       
   169     st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", _min, _max);
       
   170   }
       
   171 };
       
   172 
       
   173 class JVMFlagRange_uint64_t : public JVMFlagRange {
       
   174   uint64_t _min;
       
   175   uint64_t _max;
       
   176   const uint64_t* _ptr;
       
   177 
       
   178 public:
       
   179   // the "name" argument must be a string literal
       
   180   JVMFlagRange_uint64_t(const char* name, const uint64_t* ptr, uint64_t min, uint64_t max)
       
   181     : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
       
   182 
       
   183   JVMFlag::Error check(bool verbose = true) {
       
   184     return check_uint64_t(*_ptr, verbose);
       
   185   }
       
   186 
       
   187   JVMFlag::Error check_uint64_t(uint64_t value, bool verbose = true) {
       
   188     if ((value < _min) || (value > _max)) {
       
   189       CommandLineError::print(verbose,
       
   190                               "uint64_t %s=" UINT64_FORMAT " is outside the allowed range "
       
   191                               "[ " UINT64_FORMAT " ... " UINT64_FORMAT " ]\n",
       
   192                               name(), value, _min, _max);
       
   193       return JVMFlag::OUT_OF_BOUNDS;
       
   194     } else {
       
   195       return JVMFlag::SUCCESS;
       
   196     }
       
   197   }
       
   198 
       
   199   void print(outputStream* st) {
       
   200     st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", _min, _max);
       
   201   }
       
   202 };
       
   203 
       
   204 class JVMFlagRange_size_t : public JVMFlagRange {
       
   205   size_t _min;
       
   206   size_t _max;
       
   207   const size_t* _ptr;
       
   208 
       
   209 public:
       
   210   // the "name" argument must be a string literal
       
   211   JVMFlagRange_size_t(const char* name, const size_t* ptr, size_t min, size_t max)
       
   212     : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
       
   213 
       
   214   JVMFlag::Error check(bool verbose = true) {
       
   215     return check_size_t(*_ptr, verbose);
       
   216   }
       
   217 
       
   218   JVMFlag::Error check_size_t(size_t value, bool verbose = true) {
       
   219     if ((value < _min) || (value > _max)) {
       
   220       CommandLineError::print(verbose,
       
   221                               "size_t %s=" SIZE_FORMAT " is outside the allowed range "
       
   222                               "[ " SIZE_FORMAT " ... " SIZE_FORMAT " ]\n",
       
   223                               name(), value, _min, _max);
       
   224       return JVMFlag::OUT_OF_BOUNDS;
       
   225     } else {
       
   226       return JVMFlag::SUCCESS;
       
   227     }
       
   228   }
       
   229 
       
   230   void print(outputStream* st) {
       
   231     st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", _min, _max);
       
   232   }
       
   233 };
       
   234 
       
   235 class JVMFlagRange_double : public JVMFlagRange {
       
   236   double _min;
       
   237   double _max;
       
   238   const double* _ptr;
       
   239 
       
   240 public:
       
   241   // the "name" argument must be a string literal
       
   242   JVMFlagRange_double(const char* name, const double* ptr, double min, double max)
       
   243     : JVMFlagRange(name), _min(min), _max(max), _ptr(ptr) {}
       
   244 
       
   245   JVMFlag::Error check(bool verbose = true) {
       
   246     return check_double(*_ptr, verbose);
       
   247   }
       
   248 
       
   249   JVMFlag::Error check_double(double value, bool verbose = true) {
       
   250     if ((value < _min) || (value > _max)) {
       
   251       CommandLineError::print(verbose,
       
   252                               "double %s=%f is outside the allowed range "
       
   253                               "[ %f ... %f ]\n",
       
   254                               name(), value, _min, _max);
       
   255       return JVMFlag::OUT_OF_BOUNDS;
       
   256     } else {
       
   257       return JVMFlag::SUCCESS;
       
   258     }
       
   259   }
       
   260 
       
   261   void print(outputStream* st) {
       
   262     st->print("[ %-25.3f ... %25.3f ]", _min, _max);
       
   263   }
       
   264 };
       
   265 
       
   266 // No constraint emitting
       
   267 void emit_range_no(...)                         { /* NOP */ }
       
   268 
       
   269 // No constraint emitting if function argument is NOT provided
       
   270 void emit_range_bool(const char* /*name*/, const bool* /*value*/)            { /* NOP */ }
       
   271 void emit_range_ccstr(const char* /*name*/, const ccstr* /*value*/)          { /* NOP */ }
       
   272 void emit_range_ccstrlist(const char* /*name*/, const ccstrlist* /*value*/)  { /* NOP */ }
       
   273 void emit_range_int(const char* /*name*/, const int* /*value*/)              { /* NOP */ }
       
   274 void emit_range_intx(const char* /*name*/, const intx* /*value*/)            { /* NOP */ }
       
   275 void emit_range_uint(const char* /*name*/, const uint* /*value*/)            { /* NOP */ }
       
   276 void emit_range_uintx(const char* /*name*/, const uintx* /*value*/)          { /* NOP */ }
       
   277 void emit_range_uint64_t(const char* /*name*/, const uint64_t* /*value*/)    { /* NOP */ }
       
   278 void emit_range_size_t(const char* /*name*/, const size_t* /*value*/)        { /* NOP */ }
       
   279 void emit_range_double(const char* /*name*/, const double* /*value*/)        { /* NOP */ }
       
   280 
       
   281 // JVMFlagRange emitting code functions if range arguments are provided
       
   282 void emit_range_int(const char* name, const int* ptr, int min, int max)       {
       
   283   JVMFlagRangeList::add(new JVMFlagRange_int(name, ptr, min, max));
       
   284 }
       
   285 void emit_range_intx(const char* name, const intx* ptr, intx min, intx max) {
       
   286   JVMFlagRangeList::add(new JVMFlagRange_intx(name, ptr, min, max));
       
   287 }
       
   288 void emit_range_uint(const char* name, const uint* ptr, uint min, uint max) {
       
   289   JVMFlagRangeList::add(new JVMFlagRange_uint(name, ptr, min, max));
       
   290 }
       
   291 void emit_range_uintx(const char* name, const uintx* ptr, uintx min, uintx max) {
       
   292   JVMFlagRangeList::add(new JVMFlagRange_uintx(name, ptr, min, max));
       
   293 }
       
   294 void emit_range_uint64_t(const char* name, const uint64_t* ptr, uint64_t min, uint64_t max) {
       
   295   JVMFlagRangeList::add(new JVMFlagRange_uint64_t(name, ptr, min, max));
       
   296 }
       
   297 void emit_range_size_t(const char* name, const size_t* ptr, size_t min, size_t max) {
       
   298   JVMFlagRangeList::add(new JVMFlagRange_size_t(name, ptr, min, max));
       
   299 }
       
   300 void emit_range_double(const char* name, const double* ptr, double min, double max) {
       
   301   JVMFlagRangeList::add(new JVMFlagRange_double(name, ptr, min, max));
       
   302 }
       
   303 
       
   304 // Generate code to call emit_range_xxx function
       
   305 #define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc)      ); emit_range_##type(#name,&name
       
   306 #define EMIT_RANGE_COMMERCIAL_FLAG(type, name, value, doc)   ); emit_range_##type(#name,&name
       
   307 #define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc)   ); emit_range_##type(#name,&name
       
   308 #define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_range_##type(#name,&name
       
   309 #define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc)   ); emit_range_##type(#name,&name
       
   310 #define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc)   ); emit_range_##type(#name,&name
       
   311 #define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc)          ); emit_range_##type(#name,&name
       
   312 #define EMIT_RANGE_PD_DIAGNOSTIC_FLAG(type, name, doc)       ); emit_range_##type(#name,&name
       
   313 #ifndef PRODUCT
       
   314 #define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc)    ); emit_range_##type(#name,&name
       
   315 #define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_range_##type(#name,&name
       
   316 #define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_range_##type(#name,&name
       
   317 #else
       
   318 #define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc)    ); emit_range_no(#name,&name
       
   319 #define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_range_no(#name,&name
       
   320 #define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_range_no(#name,&name
       
   321 #endif
       
   322 #ifdef _LP64
       
   323 #define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name,&name
       
   324 #else
       
   325 #define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_range_no(#name,&name
       
   326 #endif
       
   327 
       
   328 // Generate func argument to pass into emit_range_xxx functions
       
   329 #define EMIT_RANGE_CHECK(a, b)                               , a, b
       
   330 
       
   331 #define INITIAL_RANGES_SIZE 379
       
   332 GrowableArray<JVMFlagRange*>* JVMFlagRangeList::_ranges = NULL;
       
   333 
       
   334 // Check the ranges of all flags that have them
       
   335 void JVMFlagRangeList::init(void) {
       
   336 
       
   337   _ranges = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<JVMFlagRange*>(INITIAL_RANGES_SIZE, true);
       
   338 
       
   339   emit_range_no(NULL VM_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
       
   340                               EMIT_RANGE_PD_DEVELOPER_FLAG,
       
   341                               EMIT_RANGE_PRODUCT_FLAG,
       
   342                               EMIT_RANGE_PD_PRODUCT_FLAG,
       
   343                               EMIT_RANGE_DIAGNOSTIC_FLAG,
       
   344                               EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
       
   345                               EMIT_RANGE_EXPERIMENTAL_FLAG,
       
   346                               EMIT_RANGE_NOTPRODUCT_FLAG,
       
   347                               EMIT_RANGE_MANAGEABLE_FLAG,
       
   348                               EMIT_RANGE_PRODUCT_RW_FLAG,
       
   349                               EMIT_RANGE_LP64_PRODUCT_FLAG,
       
   350                               EMIT_RANGE_CHECK,
       
   351                               IGNORE_CONSTRAINT,
       
   352                               IGNORE_WRITEABLE));
       
   353 
       
   354   EMIT_RANGES_FOR_GLOBALS_EXT
       
   355 
       
   356   emit_range_no(NULL ARCH_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
       
   357                                 EMIT_RANGE_PRODUCT_FLAG,
       
   358                                 EMIT_RANGE_DIAGNOSTIC_FLAG,
       
   359                                 EMIT_RANGE_EXPERIMENTAL_FLAG,
       
   360                                 EMIT_RANGE_NOTPRODUCT_FLAG,
       
   361                                 EMIT_RANGE_CHECK,
       
   362                                 IGNORE_CONSTRAINT,
       
   363                                 IGNORE_WRITEABLE));
       
   364 
       
   365 #if INCLUDE_JVMCI
       
   366   emit_range_no(NULL JVMCI_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
       
   367                                  EMIT_RANGE_PD_DEVELOPER_FLAG,
       
   368                                  EMIT_RANGE_PRODUCT_FLAG,
       
   369                                  EMIT_RANGE_PD_PRODUCT_FLAG,
       
   370                                  EMIT_RANGE_DIAGNOSTIC_FLAG,
       
   371                                  EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
       
   372                                  EMIT_RANGE_EXPERIMENTAL_FLAG,
       
   373                                  EMIT_RANGE_NOTPRODUCT_FLAG,
       
   374                                  EMIT_RANGE_CHECK,
       
   375                                  IGNORE_CONSTRAINT,
       
   376                                  IGNORE_WRITEABLE));
       
   377 #endif // INCLUDE_JVMCI
       
   378 
       
   379 #ifdef COMPILER1
       
   380   emit_range_no(NULL C1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
       
   381                               EMIT_RANGE_PD_DEVELOPER_FLAG,
       
   382                               EMIT_RANGE_PRODUCT_FLAG,
       
   383                               EMIT_RANGE_PD_PRODUCT_FLAG,
       
   384                               EMIT_RANGE_DIAGNOSTIC_FLAG,
       
   385                               EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
       
   386                               EMIT_RANGE_NOTPRODUCT_FLAG,
       
   387                               EMIT_RANGE_CHECK,
       
   388                               IGNORE_CONSTRAINT,
       
   389                               IGNORE_WRITEABLE));
       
   390 #endif // COMPILER1
       
   391 
       
   392 #ifdef COMPILER2
       
   393   emit_range_no(NULL C2_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
       
   394                               EMIT_RANGE_PD_DEVELOPER_FLAG,
       
   395                               EMIT_RANGE_PRODUCT_FLAG,
       
   396                               EMIT_RANGE_PD_PRODUCT_FLAG,
       
   397                               EMIT_RANGE_DIAGNOSTIC_FLAG,
       
   398                               EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
       
   399                               EMIT_RANGE_EXPERIMENTAL_FLAG,
       
   400                               EMIT_RANGE_NOTPRODUCT_FLAG,
       
   401                               EMIT_RANGE_CHECK,
       
   402                               IGNORE_CONSTRAINT,
       
   403                               IGNORE_WRITEABLE));
       
   404 #endif // COMPILER2
       
   405 }
       
   406 
       
   407 JVMFlagRange* JVMFlagRangeList::find(const char* name) {
       
   408   JVMFlagRange* found = NULL;
       
   409   for (int i=0; i<length(); i++) {
       
   410     JVMFlagRange* range = at(i);
       
   411     if (strcmp(range->name(), name) == 0) {
       
   412       found = range;
       
   413       break;
       
   414     }
       
   415   }
       
   416   return found;
       
   417 }
       
   418 
       
   419 void JVMFlagRangeList::print(outputStream* st, const char* name, RangeStrFunc default_range_str_func) {
       
   420   JVMFlagRange* range = JVMFlagRangeList::find(name);
       
   421   if (range != NULL) {
       
   422     range->print(st);
       
   423   } else {
       
   424     JVMFlagConstraint* constraint = JVMFlagConstraintList::find(name);
       
   425     if (constraint != NULL) {
       
   426       assert(default_range_str_func!=NULL, "default_range_str_func must be provided");
       
   427       st->print("%s", default_range_str_func());
       
   428     } else {
       
   429       st->print("[                           ...                           ]");
       
   430     }
       
   431   }
       
   432 }
       
   433 
       
   434 bool JVMFlagRangeList::check_ranges() {
       
   435   // Check ranges.
       
   436   bool status = true;
       
   437   for (int i=0; i<length(); i++) {
       
   438     JVMFlagRange* range = at(i);
       
   439     if (range->check(true) != JVMFlag::SUCCESS) status = false;
       
   440   }
       
   441   return status;
       
   442 }