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