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