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