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 "utilities/defaultStream.hpp"
  33 #include "utilities/macros.hpp"
  34 
  35 static void print_range_error_if_needed(bool verbose, const char* msg, ...) {
  36   if (verbose) {
  37     va_list listPointer;
  38     va_start(listPointer, msg);
  39     jio_fprintf(defaultStream::error_stream(), msg, listPointer);
  40     va_end(listPointer);
  41   }
  42 }
  43 
  44 class CommandLineFlagRange_int : public CommandLineFlagRange {
  45   int _min;
  46   int _max;
  47 
  48 public:
  49   // the "name" argument must be a string literal
  50   CommandLineFlagRange_int(const char* name, int min, int max) : CommandLineFlagRange(name) {
  51     _min=min, _max=max;
  52   }
  53 
  54   Flag::Error check_int(int value, bool verbose = true) {
  55     if ((value < _min) || (value > _max)) {
  56       print_range_error_if_needed(verbose, "int %s=%d is outside the allowed range [ %d ... %d ]\n",
  57                                   name(), value, _min, _max);
  58       return Flag::OUT_OF_BOUNDS;
  59     } else {
  60       return Flag::SUCCESS;
  61     }
  62   }
  63 
  64   void print(outputStream* st) {
  65     st->print("[ %-25d ... %25d ]", _min, _max);
  66   }
  67 };
  68 
  69 class CommandLineFlagRange_intx : public CommandLineFlagRange {
  70   intx _min;
  71   intx _max;
  72 
  73 public:
  74   // the "name" argument must be a string literal
  75   CommandLineFlagRange_intx(const char* name, intx min, intx max) : CommandLineFlagRange(name) {
  76     _min=min, _max=max;
  77   }
  78 
  79   Flag::Error check_intx(intx value, bool verbose = true) {
  80     if ((value < _min) || (value > _max)) {
  81       print_range_error_if_needed(verbose, "intx %s=" INTX_FORMAT " is outside the allowed range [ " INTX_FORMAT " ... " INTX_FORMAT " ]\n",
  82                                   name(), value, _min, _max);
  83       return Flag::OUT_OF_BOUNDS;
  84     } else {
  85       return Flag::SUCCESS;
  86     }
  87   }
  88 
  89   void print(outputStream* st) {
  90     st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", _min, _max);
  91   }
  92 };
  93 
  94 class CommandLineFlagRange_uint : public CommandLineFlagRange {
  95   uint _min;
  96   uint _max;
  97 
  98 public:
  99   // the "name" argument must be a string literal
 100   CommandLineFlagRange_uint(const char* name, uint min, uint max) : CommandLineFlagRange(name) {
 101     _min=min, _max=max;
 102   }
 103 
 104   Flag::Error check_uint(uint value, bool verbose = true) {
 105     if ((value < _min) || (value > _max)) {
 106       print_range_error_if_needed(verbose, "uint %s=%u is outside the allowed range [ %u ... %u ]\n",
 107                                   name(), value, _min, _max);
 108       return Flag::OUT_OF_BOUNDS;
 109     } else {
 110       return Flag::SUCCESS;
 111     }
 112   }
 113 
 114   void print(outputStream* st) {
 115     st->print("[ %-25u ... %25u ]", _min, _max);
 116   }
 117 };
 118 
 119 class CommandLineFlagRange_uintx : public CommandLineFlagRange {
 120   uintx _min;
 121   uintx _max;
 122 
 123 public:
 124   // the "name" argument must be a string literal
 125   CommandLineFlagRange_uintx(const char* name, uintx min, uintx max) : CommandLineFlagRange(name) {
 126     _min=min, _max=max;
 127   }
 128 
 129   Flag::Error check_uintx(uintx value, bool verbose = true) {
 130     if ((value < _min) || (value > _max)) {
 131       print_range_error_if_needed(verbose, "uintx %s=" UINTX_FORMAT " is outside the allowed range [ " UINTX_FORMAT " ... " UINTX_FORMAT " ]\n",
 132                                   name(), value, _min, _max);
 133       return Flag::OUT_OF_BOUNDS;
 134     } else {
 135       return Flag::SUCCESS;
 136     }
 137   }
 138 
 139   void print(outputStream* st) {
 140     st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", _min, _max);
 141   }
 142 };
 143 
 144 class CommandLineFlagRange_uint64_t : public CommandLineFlagRange {
 145   uint64_t _min;
 146   uint64_t _max;
 147 
 148 public:
 149   // the "name" argument must be a string literal
 150   CommandLineFlagRange_uint64_t(const char* name, uint64_t min, uint64_t max) : CommandLineFlagRange(name) {
 151     _min=min, _max=max;
 152   }
 153 
 154   Flag::Error check_uint64_t(uint64_t value, bool verbose = true) {
 155     if ((value < _min) || (value > _max)) {
 156       print_range_error_if_needed(verbose, "uint64_t %s=" UINT64_FORMAT " is outside the allowed range [ " UINT64_FORMAT " ... " UINT64_FORMAT " ]\n",
 157                                   name(), value, _min, _max);
 158       return Flag::OUT_OF_BOUNDS;
 159     } else {
 160       return Flag::SUCCESS;
 161     }
 162   }
 163 
 164   void print(outputStream* st) {
 165     st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", _min, _max);
 166   }
 167 };
 168 
 169 class CommandLineFlagRange_size_t : public CommandLineFlagRange {
 170   size_t _min;
 171   size_t _max;
 172 
 173 public:
 174   // the "name" argument must be a string literal
 175   CommandLineFlagRange_size_t(const char* name, size_t min, size_t max) : CommandLineFlagRange(name) {
 176     _min=min, _max=max;
 177   }
 178 
 179   Flag::Error check_size_t(size_t value, bool verbose = true) {
 180     if ((value < _min) || (value > _max)) {
 181       print_range_error_if_needed(verbose, "size_t %s=" SIZE_FORMAT " is outside the allowed range [ " SIZE_FORMAT " ... " SIZE_FORMAT " ]\n",
 182                                   name(), value, _min, _max);
 183       return Flag::OUT_OF_BOUNDS;
 184     } else {
 185       return Flag::SUCCESS;
 186     }
 187   }
 188 
 189   void print(outputStream* st) {
 190     st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", _min, _max);
 191   }
 192 };
 193 
 194 class CommandLineFlagRange_double : public CommandLineFlagRange {
 195   double _min;
 196   double _max;
 197 
 198 public:
 199   // the "name" argument must be a string literal
 200   CommandLineFlagRange_double(const char* name, double min, double max) : CommandLineFlagRange(name) {
 201     _min=min, _max=max;
 202   }
 203 
 204   Flag::Error check_double(double value, bool verbose = true) {
 205     if ((value < _min) || (value > _max)) {
 206       print_range_error_if_needed(verbose, "double %s=%f is outside the allowed range [ %f ... %f ]\n",
 207                                   name(), value, _min, _max);
 208       return Flag::OUT_OF_BOUNDS;
 209     } else {
 210       return Flag::SUCCESS;
 211     }
 212   }
 213 
 214   void print(outputStream* st) {
 215     st->print("[ %-25.3f ... %25.3f ]", _min, _max);
 216   }
 217 };
 218 
 219 // No constraint emitting
 220 void emit_range_no(...)                         { /* NOP */ }
 221 
 222 // No constraint emitting if function argument is NOT provided
 223 void emit_range_bool(const char* /*name*/)      { /* NOP */ }
 224 void emit_range_ccstr(const char* /*name*/)     { /* NOP */ }
 225 void emit_range_ccstrlist(const char* /*name*/) { /* NOP */ }
 226 void emit_range_int(const char* /*name*/)       { /* NOP */ }
 227 void emit_range_intx(const char* /*name*/)      { /* NOP */ }
 228 void emit_range_uint(const char* /*name*/)      { /* NOP */ }
 229 void emit_range_uintx(const char* /*name*/)     { /* NOP */ }
 230 void emit_range_uint64_t(const char* /*name*/)  { /* NOP */ }
 231 void emit_range_size_t(const char* /*name*/)    { /* NOP */ }
 232 void emit_range_double(const char* /*name*/)    { /* NOP */ }
 233 
 234 // CommandLineFlagRange emitting code functions if range arguments are provided
 235 void emit_range_intx(const char* name, intx min, intx max) {
 236   CommandLineFlagRangeList::add(new CommandLineFlagRange_intx(name, min, max));
 237 }
 238 void emit_range_uintx(const char* name, uintx min, uintx max) {
 239   CommandLineFlagRangeList::add(new CommandLineFlagRange_uintx(name, min, max));
 240 }
 241 void emit_range_uint64_t(const char* name, uint64_t min, uint64_t max) {
 242   CommandLineFlagRangeList::add(new CommandLineFlagRange_uint64_t(name, min, max));
 243 }
 244 void emit_range_size_t(const char* name, size_t min, size_t max) {
 245   CommandLineFlagRangeList::add(new CommandLineFlagRange_size_t(name, min, max));
 246 }
 247 void emit_range_double(const char* name, double min, double max) {
 248   CommandLineFlagRangeList::add(new CommandLineFlagRange_double(name, min, max));
 249 }
 250 
 251 // Generate code to call emit_range_xxx function
 252 #define EMIT_RANGE_PRODUCT_FLAG(type, name, value, doc)      ); emit_range_##type(#name
 253 #define EMIT_RANGE_COMMERCIAL_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 254 #define EMIT_RANGE_DIAGNOSTIC_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 255 #define EMIT_RANGE_EXPERIMENTAL_FLAG(type, name, value, doc) ); emit_range_##type(#name
 256 #define EMIT_RANGE_MANAGEABLE_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 257 #define EMIT_RANGE_PRODUCT_RW_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 258 #define EMIT_RANGE_PD_PRODUCT_FLAG(type, name, doc)          ); emit_range_##type(#name
 259 #define EMIT_RANGE_DEVELOPER_FLAG(type, name, value, doc)    ); emit_range_##type(#name
 260 #define EMIT_RANGE_PD_DEVELOPER_FLAG(type, name, doc)        ); emit_range_##type(#name
 261 #define EMIT_RANGE_NOTPRODUCT_FLAG(type, name, value, doc)   ); emit_range_##type(#name
 262 #define EMIT_RANGE_LP64_PRODUCT_FLAG(type, name, value, doc) ); emit_range_##type(#name
 263 
 264 // Generate func argument to pass into emit_range_xxx functions
 265 #define EMIT_RANGE_CHECK(a, b)                               , a, b
 266 
 267 #define INITIAL_RANGES_SIZE 128
 268 GrowableArray<CommandLineFlagRange*>* CommandLineFlagRangeList::_ranges = NULL;
 269 
 270 // Check the ranges of all flags that have them
 271 void CommandLineFlagRangeList::init(void) {
 272 
 273   _ranges = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<CommandLineFlagRange*>(INITIAL_RANGES_SIZE, true);
 274 
 275   emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 276                                    EMIT_RANGE_PD_DEVELOPER_FLAG,
 277                                    EMIT_RANGE_PRODUCT_FLAG,
 278                                    EMIT_RANGE_PD_PRODUCT_FLAG,
 279                                    EMIT_RANGE_DIAGNOSTIC_FLAG,
 280                                    EMIT_RANGE_EXPERIMENTAL_FLAG,
 281                                    EMIT_RANGE_NOTPRODUCT_FLAG,
 282                                    EMIT_RANGE_MANAGEABLE_FLAG,
 283                                    EMIT_RANGE_PRODUCT_RW_FLAG,
 284                                    EMIT_RANGE_LP64_PRODUCT_FLAG,
 285                                    EMIT_RANGE_CHECK,
 286                                    IGNORE_CONSTRAINT) );
 287 
 288   EMIT_RANGES_FOR_GLOBALS_EXT
 289 
 290   emit_range_no(NULL ARCH_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 291                                      EMIT_RANGE_PRODUCT_FLAG,
 292                                      EMIT_RANGE_DIAGNOSTIC_FLAG,
 293                                      EMIT_RANGE_EXPERIMENTAL_FLAG,
 294                                      EMIT_RANGE_NOTPRODUCT_FLAG,
 295                                      EMIT_RANGE_CHECK,
 296                                      IGNORE_CONSTRAINT));
 297 
 298 #ifdef COMPILER1
 299   emit_range_no(NULL C1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 300                                    EMIT_RANGE_PD_DEVELOPER_FLAG,
 301                                    EMIT_RANGE_PRODUCT_FLAG,
 302                                    EMIT_RANGE_PD_PRODUCT_FLAG,
 303                                    EMIT_RANGE_DIAGNOSTIC_FLAG,
 304                                    EMIT_RANGE_NOTPRODUCT_FLAG,
 305                                    EMIT_RANGE_CHECK,
 306                                    IGNORE_CONSTRAINT));
 307 #endif // COMPILER1
 308 
 309 #ifdef COMPILER2
 310   emit_range_no(NULL C2_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 311                                    EMIT_RANGE_PD_DEVELOPER_FLAG,
 312                                    EMIT_RANGE_PRODUCT_FLAG,
 313                                    EMIT_RANGE_PD_PRODUCT_FLAG,
 314                                    EMIT_RANGE_DIAGNOSTIC_FLAG,
 315                                    EMIT_RANGE_EXPERIMENTAL_FLAG,
 316                                    EMIT_RANGE_NOTPRODUCT_FLAG,
 317                                    EMIT_RANGE_CHECK,
 318                                    IGNORE_CONSTRAINT));
 319 #endif // COMPILER2
 320 
 321 #if INCLUDE_ALL_GCS
 322   emit_range_no(NULL G1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
 323                                    EMIT_RANGE_PD_DEVELOPER_FLAG,
 324                                    EMIT_RANGE_PRODUCT_FLAG,
 325                                    EMIT_RANGE_PD_PRODUCT_FLAG,
 326                                    EMIT_RANGE_DIAGNOSTIC_FLAG,
 327                                    EMIT_RANGE_EXPERIMENTAL_FLAG,
 328                                    EMIT_RANGE_NOTPRODUCT_FLAG,
 329                                    EMIT_RANGE_MANAGEABLE_FLAG,
 330                                    EMIT_RANGE_PRODUCT_RW_FLAG,
 331                                    EMIT_RANGE_CHECK,
 332                                    IGNORE_CONSTRAINT));
 333 #endif // INCLUDE_ALL_GCS
 334 }
 335 
 336 CommandLineFlagRange* CommandLineFlagRangeList::find(const char* name) {
 337   CommandLineFlagRange* found = NULL;
 338   for (int i=0; i<length(); i++) {
 339     CommandLineFlagRange* range = at(i);
 340     if (strcmp(range->name(), name) == 0) {
 341       found = range;
 342       break;
 343     }
 344   }
 345   return found;
 346 }
 347 
 348 void CommandLineFlagRangeList::print(const char* name, outputStream* st, bool unspecified) {
 349   CommandLineFlagRange* range = CommandLineFlagRangeList::find(name);
 350   if (range != NULL) {
 351     range->print(st);
 352   } else if (unspecified == true) {
 353     st->print("[                           ...                           ]");
 354   }
 355 }