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