1 /*
   2  * Copyright (c) 1997, 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 #ifndef SHARE_RUNTIME_FLAGS_JVMFLAG_HPP
  26 #define SHARE_RUNTIME_FLAGS_JVMFLAG_HPP
  27 
  28 #include "utilities/globalDefinitions.hpp"
  29 #include "utilities/macros.hpp"
  30 
  31 class outputStream;
  32 
  33 // function type that will construct default range string
  34 typedef const char* (*RangeStrFunc)(void);
  35 
  36 struct JVMFlag {
  37   friend class VMStructs;
  38   friend class JVMCIVMStructs;
  39 
  40   enum Attr {
  41     DEFAULT          = 0,
  42     COMMAND_LINE     = 1,
  43     ENVIRON_VAR      = 2,
  44     CONFIG_FILE      = 3,
  45     MANAGEMENT       = 4,
  46     ERGONOMIC        = 5,
  47     ATTACH_ON_DEMAND = 6,
  48     INTERNAL         = 7,
  49     JIMAGE_RESOURCE  = 8,
  50 
  51     LAST_VALUE_ORIGIN = JIMAGE_RESOURCE,
  52     VALUE_ORIGIN_BITS = 4,
  53     VALUE_ORIGIN_MASK = right_n_bits(VALUE_ORIGIN_BITS),
  54 
  55     IS_PRODUCT         = 1 << 4,
  56     MANAGEABLE         = 1 << 5,
  57     DIAGNOSTIC         = 1 << 6,
  58     EXPERIMENTAL       = 1 << 7,
  59     NOT_PRODUCT        = 1 << 8,
  60     DEVELOP            = 1 << 9,
  61     PLATFORM_DEPENDENT = 1 << 10,
  62     READ_WRITE         = 1 << 11,
  63     C1                 = 1 << 12,
  64     C2                 = 1 << 13,
  65     ARCH               = 1 << 14,
  66     LP64               = 1 << 15,
  67     JVMCI              = 1 << 16,
  68 
  69     STRINGLIST         = 1 << 17, // replaces the old ccstrlist -- TODO document
  70     RANGE              = 1 << 18, // -- TODO document
  71     CONSTRAINT         = 1 << 19, // -- TODO document
  72 
  73     // set this bit if the flag was set on the command line
  74     ORIG_COMMAND_LINE  = 1 << 21,           // huh COMMAND_LINE and ORIG_COMMAND_LINE
  75 
  76     KIND_MASK = ~(VALUE_ORIGIN_MASK | ORIG_COMMAND_LINE | STRINGLIST | RANGE | CONSTRAINT),
  77 
  78     ALL_NOT_PRODUCT_FLAGS = DEVELOP | NOT_PRODUCT | MANAGEABLE |
  79                             EXPERIMENTAL | DIAGNOSTIC | LP64 | JVMCI
  80   };
  81 
  82   typedef Attr Flags; // compatibility for usage of JVMFlag::Flags -- TODO fix in separate RFE
  83 
  84   enum Error {
  85     // no error
  86     SUCCESS = 0,
  87     // flag name is missing
  88     MISSING_NAME,
  89     // flag value is missing
  90     MISSING_VALUE,
  91     // error parsing the textual form of the value
  92     WRONG_FORMAT,
  93     // flag is not writable
  94     NON_WRITABLE,
  95     // flag value is outside of its bounds
  96     OUT_OF_BOUNDS,
  97     // flag value violates its constraint
  98     VIOLATES_CONSTRAINT,
  99     // there is no flag with the given name
 100     INVALID_FLAG,
 101     // the flag can only be set only on command line during invocation of the VM
 102     COMMAND_LINE_ONLY,
 103     // the flag may only be set once
 104     SET_ONLY_ONCE,
 105     // the flag is not writable in this combination of product/debug build
 106     CONSTANT,
 107     // other, unspecified error related to setting the flag
 108     ERR_OTHER
 109   };
 110 
 111   enum MsgType {
 112     NONE = 0,
 113     DIAGNOSTIC_FLAG_BUT_LOCKED,
 114     EXPERIMENTAL_FLAG_BUT_LOCKED,
 115     DEVELOPER_FLAG_BUT_PRODUCT_BUILD,
 116     NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD
 117   };
 118 
 119   // During VM initialization, constraint validation will be done order of ConstraintPhase.
 120   enum ConstraintPhase {
 121     // Will be validated during argument processing (Arguments::parse_argument).
 122     AtParse         = 0,
 123     // Will be validated inside Threads::create_vm(), right after Arguments::apply_ergo().
 124     AfterErgo       = 1,
 125     // Will be validated inside universe_init(), right after Metaspace::global_initialize().
 126     AfterMemoryInit = 2
 127   };
 128 
 129 #define JVM_FLAG_ALL_TYPES_DO(f) \
 130     f(bool) \
 131     f(int) \
 132     f(uint) \
 133     f(intx) \
 134     f(uintx) \
 135     f(uint64_t) \
 136     f(size_t) \
 137     f(double) \
 138     f(ccstr)
 139 
 140 #define JVM_FLAG_TYPE_DECLARE(t) \
 141   TYPE_ ## t,
 142 
 143   // Define TYPE_bool, TYPE_int, .... etc
 144   enum FlagType {
 145     JVM_FLAG_ALL_TYPES_DO(JVM_FLAG_TYPE_DECLARE)
 146     NUM_TYPES
 147   };
 148 
 149 #define FLAG_ACCESSOR(t) \
 150   t get_##t() const { return *((t*)value_addr()); } \
 151   bool is_##t() const { return _type == JVMFlag::TYPE_ ## t; }
 152 
 153   JVM_FLAG_ALL_TYPES_DO(FLAG_ACCESSOR)
 154 
 155 private:
 156   const char* _name;
 157   int _attr;
 158   short _name_len;
 159   short _type;
 160 protected:
 161   void* _range;
 162   void* _constraint;
 163   void* _value_addr;
 164 private:
 165   NOT_PRODUCT(const char* _docs;)
 166   JVMFlag* _next;
 167   static JVMFlag* _head;
 168   static int _num_flags;
 169 
 170   static ConstraintPhase _constraint_validating_phase;
 171   static const JVMFlag* _current_checking;
 172 
 173 protected:
 174   static void set_current_checking(const JVMFlag* f) {
 175     assert(_current_checking == NULL || f == NULL, "no recursion");
 176     _current_checking = f;
 177   }
 178 
 179 public:
 180   JVMFlag(FlagType type, const char* name, int attr, void* value_addr, const char* docs) :
 181       _name(name),
 182       // So we don't need to explicitly say IS_PRODUCT all over the place!
 183       _attr(attr | ((attr & ALL_NOT_PRODUCT_FLAGS) ? 0 : IS_PRODUCT)),
 184       _name_len(0),
 185       _type(short(type)),
 186       _range(NULL),
 187       _constraint(NULL),
 188       _value_addr(value_addr),
 189       NOT_PRODUCT_ARG(_docs(docs))
 190       _next(_head) {
 191     assert(is_default(), "original must be initialized to DEFAULT");
 192     _head = this;
 193     _num_flags ++;
 194   }
 195 
 196   const char* name() const { return _name; }
 197   const char* docs() const { return  NOT_PRODUCT(_docs) PRODUCT_ONLY(""); }
 198   JVMFlag* next()    const { return _next; }
 199   int attr()         const { return _attr; }
 200   void* value_addr() const { return _value_addr; }
 201 
 202   FlagType type() const { 
 203     assert(0 <= _type && _type < JVMFlag::NUM_TYPES, "must be");
 204     return (FlagType)_type;
 205   }
 206 
 207   static JVMFlag* head() { return _head; }
 208   static int num_flags() { return _num_flags; }
 209   static const JVMFlag* current_checking() {
 210     return _current_checking;
 211   }
 212   static bool verbose_checking() { return _constraint_validating_phase < AfterErgo; };
 213 
 214   void set_origin(Flags origin);
 215   int  get_origin()             const { return _attr & VALUE_ORIGIN_MASK;        }
 216   bool is_default()             const { return (get_origin() == DEFAULT);        }
 217   bool is_ergonomic()           const { return (get_origin() == ERGONOMIC);      }
 218   bool is_command_line()        const { return (_attr & ORIG_COMMAND_LINE) != 0; }
 219 
 220   void set_command_line()             { _attr |= ORIG_COMMAND_LINE;              }
 221 
 222   bool is_product()             const { return (_attr & IS_PRODUCT) != 0;        }
 223   bool is_manageable()          const { return (_attr & MANAGEABLE) != 0;        }
 224   bool is_diagnostic()          const { return (_attr & DIAGNOSTIC) != 0;        }
 225   bool is_experimental()        const { return (_attr & EXPERIMENTAL) != 0;      }
 226   bool is_notproduct()          const { return (_attr & NOT_PRODUCT) != 0;       }
 227   bool is_develop()             const { return (_attr & DEVELOP) != 0;           }
 228   bool is_read_write()          const { return (_attr & READ_WRITE) != 0;        }
 229 
 230   bool ccstr_accumulates()      const { return is_ccstr() && (_attr & STRINGLIST) != 0; }
 231 
 232   // is this flag a constant in the JVM binary.
 233   bool is_constant_in_binary() const {
 234     return PRODUCT_ONLY(is_notproduct() || is_develop())
 235            NOT_PRODUCT(false);
 236   }
 237 
 238   bool is_writeable() const {
 239     return is_manageable() || (is_product() && is_read_write());
 240   }
 241 
 242   // All flags except "manageable" are assumed to be internal flags.
 243   // Long term, we need to define a mechanism to specify which flags
 244   // are external/stable and change this function accordingly.
 245   bool is_external() const {
 246     return is_manageable();
 247   }
 248 
 249   static void printAllFlags();
 250   const char* type_string() const;
 251 
 252   void set_range(void* range) {
 253     assert(_range == NULL, "set only once");
 254     assert((_attr & RANGE) != 0, "must be");
 255     _range = range;
 256   }
 257 
 258   void set_constraint(void* constraint) {
 259     assert(_constraint == NULL, "set only once");
 260     assert((_attr & CONSTRAINT) != 0, "must be");
 261     _constraint = constraint;
 262   }
 263 
 264   bool has_range() const { return _range != NULL; }
 265   void print_value(outputStream*) const;
 266   void print_range(outputStream*) const;
 267   JVMFlag::Error check_range(void* new_value, bool verbose) const;
 268   JVMFlag::Error check_constraint(void* new_value, bool verbose) const;
 269 
 270   static void validate_flags() PRODUCT_RETURN;
 271 
 272   // Range and constraint checking
 273   struct PrintFormat {
 274     NOT_PRODUCT(JVMFlag::FlagType type;)
 275     const char* print_value_format;
 276     const char* range_error_format;
 277     const char* print_range_format;
 278   };
 279 
 280   static PrintFormat print_formats[]; // This can be changed to a const table with c++11
 281   bool is_jimage_resource();
 282 
 283   template <typename T> inline void print_range_helper(outputStream* st, T min, T max) const;
 284   void print_range_for_constraint(outputStream* st, void* constraint_func) const;
 285   void print_attr(outputStream* st, int width) const;
 286 
 287 protected:
 288   template <typename T> inline void print_range_error(T new_value, T min, T max, bool verbose) const;
 289 
 290   template <typename T> Error check_range_helper(T new_value, T min, T max, bool verbose) const {
 291     if ((new_value < min) || (new_value > max)) {
 292       print_range_error(new_value, min, max, verbose);
 293       return JVMFlag::OUT_OF_BOUNDS;
 294     } else {
 295       return JVMFlag::SUCCESS;
 296     } 
 297   }
 298 
 299   template <typename T> Error check_constraint_helper(T new_value, void* func, ConstraintPhase phase, bool verbose) const {
 300     typedef Error ConstraintFunc(T value, bool verbose);
 301     if (phase > _constraint_validating_phase) {
 302       // This constraint is for a later phase. Don't call it now.
 303       return JVMFlag::SUCCESS;
 304     }
 305     return ((ConstraintFunc*)func)(new_value, verbose);
 306   }
 307 
 308 private:
 309   static JVMFlag* find_flag(const char* name, size_t length, bool allow_locked, bool return_flag);
 310 
 311 public:
 312   static JVMFlag* find_flag(const char* name) {
 313     return find_flag(name, strlen(name), false, false);
 314   }
 315   static const JVMFlag* find_declared_flag(const char* name, size_t length) {
 316     return find_flag(name, length, true, true);
 317   }
 318   static const JVMFlag* find_declared_flag(const char* name) {
 319     return find_declared_flag(name, strlen(name));
 320   }
 321 
 322   static JVMFlag* fuzzy_match(const char* name, size_t length, bool allow_locked = false);
 323 
 324   size_t get_name_length();
 325 
 326   bool is_unlocker() const;
 327   bool is_unlocked() const;
 328 
 329   void clear_diagnostic();
 330   void clear_experimental();
 331   void set_product();
 332 
 333   JVMFlag::MsgType get_locked_message(char*, int) const;
 334   JVMFlag::MsgType get_locked_message_ext(char*, int) const;
 335 
 336   // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
 337   void print_on(outputStream* st, bool withComments = false, bool printRanges = false) const;
 338   void print_kind(outputStream* st, unsigned int width) const;
 339   void print_origin(outputStream* st, unsigned int width) const;
 340   void print_as_flag(outputStream* st) const;
 341 
 342   static const char* flag_error_str(JVMFlag::Error error);
 343 
 344 public:
 345   static JVMFlag::Error boolAt(const JVMFlag* flag, bool* value);
 346   static JVMFlag::Error boolAtPut(JVMFlag* flag, bool value, Attr origin);
 347 
 348   static JVMFlag::Error intAt(const JVMFlag* flag, int* value);
 349   static JVMFlag::Error intAtPut(JVMFlag* flag, int value, Attr origin);
 350 
 351   static JVMFlag::Error uintAt(const JVMFlag* flag, uint* value);
 352   static JVMFlag::Error uintAtPut(JVMFlag* flag, uint value, Attr origin);
 353 
 354   static JVMFlag::Error intxAt(const JVMFlag* flag, intx* value);
 355   static JVMFlag::Error intxAtPut(JVMFlag* flag, intx value, Attr origin);
 356 
 357   static JVMFlag::Error uintxAt(const JVMFlag* flag, uintx* value);
 358   static JVMFlag::Error uintxAtPut(JVMFlag* flag, uintx value, Attr origin);
 359 
 360   static JVMFlag::Error size_tAt(const JVMFlag* flag, size_t* value);
 361   static JVMFlag::Error size_tAtPut(JVMFlag* flag, size_t value, Attr origin);
 362 
 363   static JVMFlag::Error uint64_tAt(const JVMFlag* flag, uint64_t* value);
 364   static JVMFlag::Error uint64_tAtPut(JVMFlag* flag, uint64_t value, Attr origin);
 365 
 366   static JVMFlag::Error doubleAt(const JVMFlag* flag, double* value);
 367   static JVMFlag::Error doubleAtPut(JVMFlag* flag, double value, Attr origin);
 368 
 369   static JVMFlag::Error ccstrAt(const JVMFlag* flag, ccstr* value);
 370   // Contract:  JVMFlag will make private copy of the incoming value.
 371   // Outgoing value is always malloc-ed, and caller MUST call free.
 372   static JVMFlag::Error ccstrAtPut(JVMFlag* flag, ccstr* value, Attr origin);
 373   static JVMFlag::Error ccstrAtPut(JVMFlag* flag, ccstr value, Attr origin) {
 374     return ccstrAtPut(flag, &value, origin);
 375   }
 376 
 377   static void printSetFlags(outputStream* out);
 378 
 379   // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
 380   static void printFlags(outputStream* out, bool withComments, bool printRanges = false, bool skipDefaults = false);
 381   static void printError(bool verbose, const char* msg, ...) ATTRIBUTE_PRINTF(2, 3);
 382 
 383   static bool check_all_ranges();
 384   static bool check_all_constraints(ConstraintPhase phase);
 385 
 386   static void verify() PRODUCT_RETURN;
 387 };
 388 
 389 template <typename T> class TypedJVMFlag;
 390 
 391 template <typename T> class JVMFlagRange {
 392 public:
 393   T _min;
 394   T _max;
 395   inline JVMFlagRange(TypedJVMFlag<T>* f, T min, T max);
 396 
 397   void init(T min, T max) {
 398     _min = min;
 399     _max = max;
 400   }
 401 };
 402 
 403 template <typename T> class JVMFlagConstraint {
 404 public:
 405   void* _func;
 406   JVMFlag::ConstraintPhase _phase;
 407   inline JVMFlagConstraint(TypedJVMFlag<T>* f, void* func, JVMFlag::ConstraintPhase phase);
 408 };
 409 
 410 template <typename T>
 411 class TypedJVMFlag : public JVMFlag {
 412 protected:
 413   T* value_addr() const {
 414     return (T*)_value_addr;
 415   }
 416 
 417   const JVMFlagRange<T>* range() const {
 418     return (const JVMFlagRange<T>*)_range;
 419   }
 420   const JVMFlagConstraint<T>* constraint() const {
 421     return (const JVMFlagConstraint<T>*)_constraint;
 422   }
 423 
 424 public:
 425   TypedJVMFlag(JVMFlag::FlagType type, const char* name, int attr, 
 426                T* value_addr, const char* docs) :
 427     JVMFlag(type, name, attr, (void*)value_addr, docs) {}
 428 
 429   static const TypedJVMFlag<T>* cast(const JVMFlag* flag) {
 430     return (const TypedJVMFlag<T>*)flag;
 431   }
 432 
 433   T get_value() const {
 434     return *value_addr();
 435   }
 436 
 437   void print_typed_range(outputStream* st) const {
 438     if (range() != NULL) {
 439       JVMFlag::print_range_helper(st, range()->_min,  range()->_max);
 440     } else {
 441       assert(constraint() != NULL, "must be");
 442       JVMFlag::print_range_for_constraint(st, constraint()->_func);
 443     }
 444   }
 445 
 446   JVMFlag::Error check_typed_range(void* new_value, bool verbose) const {
 447     assert(range() != NULL, "must be");
 448     T n = *((T*)new_value);
 449     return JVMFlag::check_range_helper(n, range()->_min,  range()->_max, verbose);
 450   }
 451 
 452   JVMFlag::Error check_typed_constraint(void* new_value, bool verbose) const {
 453     assert(constraint() != NULL, "must be");
 454     T n = *((T*)new_value);
 455     return check_constraint_helper(n, constraint()->_func, constraint()->_phase, verbose);
 456   }
 457 };
 458 
 459 template <typename T>
 460 inline JVMFlagRange<T>::JVMFlagRange(TypedJVMFlag<T>* f, T min, T max) {
 461   _min = min;
 462   _max = max;
 463   f->set_range(this);
 464 }
 465 
 466 template <typename T>
 467 inline JVMFlagConstraint<T>::JVMFlagConstraint(TypedJVMFlag<T>* f, void* func, JVMFlag::ConstraintPhase phase) {
 468   _func = func;
 469   _phase = phase;
 470   f->set_constraint(this);
 471 }
 472 
 473 
 474 template <typename T>
 475 class ProductFlag : public TypedJVMFlag<T> {
 476 public:
 477   ProductFlag(JVMFlag::FlagType type,  const char* name, int attr,
 478               T* value_addr, const char* docs) :
 479     TypedJVMFlag<T>(type, name, attr, value_addr, docs) {}
 480 
 481   JVMFlag::Error check_new_value(T new_value, JVMFlag::Attr origin);
 482 
 483   static ProductFlag<T>* cast(JVMFlag* flag) {
 484     return (ProductFlag<T>*)flag;
 485   }
 486 
 487   void write_value(T value) {
 488     *TypedJVMFlag<T>::value_addr() = value;
 489   }
 490 };
 491 
 492 #ifdef PRODUCT
 493 template <typename T>
 494 class DevelopFlag : public TypedJVMFlag<T> {
 495 public:
 496   DevelopFlag(JVMFlag::FlagType type, const char* name, int attr,
 497               const T* value_addr) :
 498     TypedJVMFlag<T>(type, name, attr, (T*)value_addr, "") {}
 499 };
 500 #endif // PRODUCT (class DevelopFlag)
 501 
 502 // The FLAG_COMMON_ATTRS and FLAG_ATTR macros allow you to define a group of flags all with the same
 503 // common attribute. See globals.hpp.
 504 #ifndef FLAG_COMMON_ATTRS
 505 #define FLAG_COMMON_ATTRS 0
 506 #endif
 507 #define FLAG_ATTR(attr) (attr | FLAG_COMMON_ATTRS)
 508 
 509 // ----- Macros for setting the values of the JVM flags -----
 510 #define FLAG_STRUCT(name) (FLAG_##name)
 511 #define FLAG_MEMBER_SET(name) Flag_##name##_set
 512 
 513 #define FLAG_IS_DEFAULT(name)         (FLAG_STRUCT(name).is_default())
 514 #define FLAG_IS_ERGO(name)            (FLAG_STRUCT(name).is_ergonomic())
 515 #define FLAG_IS_CMDLINE(name)         (FLAG_STRUCT(name).is_command_line())
 516 #define FLAG_IS_JIMAGE_RESOURCE(name) (FLAG_STRUCT(name).is_jimage_resource())
 517 
 518 #define FLAG_SET_DEFAULT(name, value) ((name) = (value))
 519 
 520 #define FLAG_SET_CMDLINE(name, value) (FLAG_STRUCT(name).set_command_line(), \
 521                                        FLAG_MEMBER_SET(name)(value, JVMFlag::COMMAND_LINE))
 522 #define FLAG_SET_ERGO(name, value)    (FLAG_MEMBER_SET(name)(value, JVMFlag::ERGONOMIC))
 523 #define FLAG_SET_MGMT(name, value)    (FLAG_MEMBER_SET(name)(value, JVMFlag::MANAGEMENT))
 524 
 525 #define FLAG_SET_ERGO_IF_DEFAULT(name, value) \
 526   do {                                        \
 527     if (FLAG_IS_DEFAULT(name)) {              \
 528       FLAG_SET_ERGO(name, value);             \
 529     }                                         \
 530   } while (0)
 531 
 532 #define JVMFLAG_FOR_EACH(f) \
 533   for (f = JVMFlag::head(); f != NULL; f = f->next())
 534 
 535 // ---- Macros for declaring VM flags in *globals.hpp files -----
 536 
 537 #define ALL_FLAG_COMMON(type, name, attr, docs) \
 538   typedef type FLAG_TYPE_##name; \
 539   inline JVMFlag::FlagType FLAG_TYPE_NAME_##name() { return JVMFlag::TYPE_##type; } \
 540   inline int FLAG_ATTR_##name() { return attr; } \
 541   inline const char* FLAG_DOCS_##name() { return docs; }
 542 
 543 #define PRODUCT_FLAG_COMMON(type, name, attr, docs) \
 544   ALL_FLAG_COMMON(type, name, attr, docs); \
 545   extern ProductFlag<FLAG_TYPE_##name> FLAG_##name; \
 546   inline JVMFlag::Error FLAG_MEMBER_SET(name)(type value, JVMFlag::Flags origin) { return JVMFlag::type##AtPut(&FLAG_##name, value, origin); } \
 547   extern "C" type name
 548 
 549 #define PRODUCT_FLAG(type, name, default_value, attr, docs) \
 550   inline type FLAG_DEFVAL_##name() { return default_value; } \
 551   PRODUCT_FLAG_COMMON(type, name, attr, docs)
 552 
 553 #define PRODUCT_FLAG_PD(type, name, attr, docs) \
 554   PRODUCT_FLAG_COMMON(type, name, ((attr) | JVMFlag::PLATFORM_DEPENDENT), docs)
 555 
 556 #ifdef PRODUCT
 557 // In product builds, meta information for DEVELOP_FLAG is stored in DevelopFlag<T>
 558 
 559 #define DEVELOP_FLAG_COMMON(type, name, attr, docs) \
 560   ALL_FLAG_COMMON(type, name, attr, docs); \
 561   extern DevelopFlag<FLAG_TYPE_##name> FLAG_##name
 562 
 563 #define DEVELOP_FLAG(type, name, default_value, attr, docs) \
 564   DEVELOP_FLAG_COMMON(type, name, ((attr) | JVMFlag::DEVELOP), docs); \
 565   const type name = default_value
 566 
 567 #define DEVELOP_FLAG_PD(type, name, attr, docs) \
 568   DEVELOP_FLAG_COMMON(type, name, ((attr) | JVMFlag::DEVELOP | JVMFlag::PLATFORM_DEPENDENT), docs); \
 569   const type name = pd_##name
 570 
 571 // In product builds, NOTPROD_FLAGs are not visible at all, but we
 572 // emit a typedef to make the FLAG_RANGE macro happy.
 573 #define NOTPROD_FLAG(type, name, default_value, attr, docs) \
 574   typedef type FLAG_TYPE_##name
 575 
 576 #else
 577 // !defined(PRODUCT)
 578 
 579 // In develop builds, DEVELOP_FLAG and NOTPROD_FLAG are equivalent to PRODUCT_FLAG
 580 #define NOTPROD_FLAG(type, name, default_value, attr, docs) \
 581   PRODUCT_FLAG(type, name, default_value, ((attr) | JVMFlag::NOT_PRODUCT) , docs)
 582 
 583 #define DEVELOP_FLAG(type, name, default_value, attr, docs) \
 584   PRODUCT_FLAG(type, name, default_value, ((attr) | JVMFlag::DEVELOP), docs)
 585 
 586 #define DEVELOP_FLAG_PD(type, name, attr, docs) \
 587   PRODUCT_FLAG_PD(type, name, ((attr) | JVMFlag::DEVELOP), docs)
 588 
 589 #endif // PRODUCT
 590 
 591 // ---- Macros for specifying VM flags constraints in *globals.hpp files -----
 592 
 593 #define FLAG_RANGE(name, min, max) \
 594   inline FLAG_TYPE_##name FLAG_MIN_##name() { return min;} \
 595   inline FLAG_TYPE_##name FLAG_MAX_##name() { return max;}
 596 
 597 #define FLAG_CONSTRAINT(name, func, phase) \
 598   inline void* FLAG_CONSTRAINT_FUNC_##name() { return (void*)func;} \
 599   inline JVMFlag::ConstraintPhase FLAG_CONSTRAINT_PHASE_##name() { return phase; }
 600 
 601 class JVMFlagCustomRange {
 602   JVMFlagCustomRange* _next;
 603   static JVMFlagCustomRange* _head;
 604 
 605 protected:
 606   virtual void init() = 0;
 607 
 608 public:
 609   JVMFlagCustomRange() {
 610     _next = _head;
 611     _head = this;
 612   }
 613   static void init_all() {
 614     for (JVMFlagCustomRange* r = _head; r; r = r->_next) {
 615       r->init();
 616     }
 617   }
 618 };
 619 
 620 class JVMFlagRange_VMPageSize : public JVMFlagCustomRange {
 621   JVMFlagRange<uintx> _r;
 622 protected:
 623   virtual void init();
 624 public:
 625   JVMFlagRange_VMPageSize(TypedJVMFlag<uintx>* f) :
 626     JVMFlagCustomRange(), _r(f, 0, 0) {}
 627 };
 628 
 629 class JVMFlagRange_VMAllocationGranularity :  public JVMFlagCustomRange {
 630   JVMFlagRange<size_t> _r;
 631 protected:
 632   virtual void init();
 633 public:
 634   JVMFlagRange_VMAllocationGranularity(TypedJVMFlag<size_t>* f) :
 635     JVMFlagCustomRange(), _r(f, 0, 0) {}
 636 };
 637 
 638 #define FLAG_CUSTOM_RANGE(name, which) \
 639   typedef JVMFlagRange_##which FLAG_RANGE_TYPE_##name
 640 
 641 #endif // SHARE_RUNTIME_FLAGS_JVMFLAG_HPP