< prev index next >

src/hotspot/share/runtime/flags/jvmFlag.hpp

Print this page

@@ -32,12 +32,14 @@
 
 // function type that will construct default range string
 typedef const char* (*RangeStrFunc)(void);
 
 struct JVMFlag {
-  enum Flags {
-    // latest value origin
+  friend class VMStructs;
+  friend class JVMCIVMStructs;
+
+  enum Attr {
     DEFAULT          = 0,
     COMMAND_LINE     = 1,
     ENVIRON_VAR      = 2,
     CONFIG_FILE      = 3,
     MANAGEMENT       = 4,

@@ -48,31 +50,39 @@
 
     LAST_VALUE_ORIGIN = JIMAGE_RESOURCE,
     VALUE_ORIGIN_BITS = 4,
     VALUE_ORIGIN_MASK = right_n_bits(VALUE_ORIGIN_BITS),
 
-    // flag kind
-    KIND_PRODUCT            = 1 << 4,
-    KIND_MANAGEABLE         = 1 << 5,
-    KIND_DIAGNOSTIC         = 1 << 6,
-    KIND_EXPERIMENTAL       = 1 << 7,
-    KIND_NOT_PRODUCT        = 1 << 8,
-    KIND_DEVELOP            = 1 << 9,
-    KIND_PLATFORM_DEPENDENT = 1 << 10,
-    KIND_READ_WRITE         = 1 << 11,
-    KIND_C1                 = 1 << 12,
-    KIND_C2                 = 1 << 13,
-    KIND_ARCH               = 1 << 14,
-    KIND_LP64_PRODUCT       = 1 << 15,
-    KIND_JVMCI              = 1 << 16,
+    IS_PRODUCT         = 1 << 4,
+    MANAGEABLE         = 1 << 5,
+    DIAGNOSTIC         = 1 << 6,
+    EXPERIMENTAL       = 1 << 7,
+    NOT_PRODUCT        = 1 << 8,
+    DEVELOP            = 1 << 9,
+    PLATFORM_DEPENDENT = 1 << 10,
+    READ_WRITE         = 1 << 11,
+    C1                 = 1 << 12,
+    C2                 = 1 << 13,
+    ARCH               = 1 << 14,
+    LP64               = 1 << 15,
+    JVMCI              = 1 << 16,
+
+    STRINGLIST         = 1 << 17, // replaces the old ccstrlist -- TODO document
+    RANGE              = 1 << 18, // -- TODO document
+    CONSTRAINT         = 1 << 19, // -- TODO document
 
     // set this bit if the flag was set on the command line
-    ORIG_COMMAND_LINE       = 1 << 17,
+    ORIG_COMMAND_LINE  = 1 << 21,           // huh COMMAND_LINE and ORIG_COMMAND_LINE
+
+    KIND_MASK = ~(VALUE_ORIGIN_MASK | ORIG_COMMAND_LINE | STRINGLIST | RANGE | CONSTRAINT),
 
-    KIND_MASK = ~(VALUE_ORIGIN_MASK | ORIG_COMMAND_LINE)
+    ALL_NOT_PRODUCT_FLAGS = DEVELOP | NOT_PRODUCT | MANAGEABLE |
+                            EXPERIMENTAL | DIAGNOSTIC | LP64 | JVMCI
   };
 
+  typedef Attr Flags; // compatibility for usage of JVMFlag::Flags -- TODO fix in separate RFE
+
   enum Error {
     // no error
     SUCCESS = 0,
     // flag name is missing
     MISSING_NAME,

@@ -104,22 +114,198 @@
     EXPERIMENTAL_FLAG_BUT_LOCKED,
     DEVELOPER_FLAG_BUT_PRODUCT_BUILD,
     NOTPRODUCT_FLAG_BUT_PRODUCT_BUILD
   };
 
-  const char* _type;
+  // During VM initialization, constraint validation will be done order of ConstraintPhase.
+  enum ConstraintPhase {
+    // Will be validated during argument processing (Arguments::parse_argument).
+    AtParse         = 0,
+    // Will be validated inside Threads::create_vm(), right after Arguments::apply_ergo().
+    AfterErgo       = 1,
+    // Will be validated inside universe_init(), right after Metaspace::global_initialize().
+    AfterMemoryInit = 2
+  };
+
+#define JVM_FLAG_ALL_TYPES_DO(f) \
+    f(bool) \
+    f(int) \
+    f(uint) \
+    f(intx) \
+    f(uintx) \
+    f(uint64_t) \
+    f(size_t) \
+    f(double) \
+    f(ccstr)
+
+#define JVM_FLAG_TYPE_DECLARE(t) \
+  TYPE_ ## t,
+
+  // Define TYPE_bool, TYPE_int, .... etc
+  enum FlagType {
+    JVM_FLAG_ALL_TYPES_DO(JVM_FLAG_TYPE_DECLARE)
+    NUM_TYPES
+  };
+
+#define FLAG_ACCESSOR(t) \
+  t get_##t() const { return *((t*)value_addr()); } \
+  bool is_##t() const { return _type == JVMFlag::TYPE_ ## t; }
+
+  JVM_FLAG_ALL_TYPES_DO(FLAG_ACCESSOR)
+
+private:
   const char* _name;
-  void* _addr;
-  NOT_PRODUCT(const char* _doc;)
-  Flags _flags;
-  size_t _name_len;
+  int _attr;
+  short _name_len;
+  short _type;
+protected:
+  void* _range;
+  void* _constraint;
+  void* _value_addr;
+private:
+  NOT_PRODUCT(const char* _docs;)
+  JVMFlag* _next;
+  static JVMFlag* _head;
+  static int _num_flags;
+
+  static ConstraintPhase _constraint_validating_phase;
+  static const JVMFlag* _current_checking;
+
+protected:
+  static void set_current_checking(const JVMFlag* f) {
+    assert(_current_checking == NULL || f == NULL, "no recursion");
+    _current_checking = f;
+  }
+
+public:
+  JVMFlag(FlagType type, const char* name, int attr, void* value_addr, const char* docs) :
+      _name(name),
+      // So we don't need to explicitly say IS_PRODUCT all over the place!
+      _attr(attr | ((attr & ALL_NOT_PRODUCT_FLAGS) ? 0 : IS_PRODUCT)),
+      _name_len(0),
+      _type(short(type)),
+      _range(NULL),
+      _constraint(NULL),
+      _value_addr(value_addr),
+      NOT_PRODUCT_ARG(_docs(docs))
+      _next(_head) {
+    assert(is_default(), "original must be initialized to DEFAULT");
+    _head = this;
+    _num_flags ++;
+  }
+
+  const char* name() const { return _name; }
+  const char* docs() const { return  NOT_PRODUCT(_docs) PRODUCT_ONLY(""); }
+  JVMFlag* next()    const { return _next; }
+  int attr()         const { return _attr; }
+  void* value_addr() const { return _value_addr; }
+
+  FlagType type() const { 
+    assert(0 <= _type && _type < JVMFlag::NUM_TYPES, "must be");
+    return (FlagType)_type;
+  }
+
+  static JVMFlag* head() { return _head; }
+  static int num_flags() { return _num_flags; }
+  static const JVMFlag* current_checking() {
+    return _current_checking;
+  }
+  static bool verbose_checking() { return _constraint_validating_phase < AfterErgo; };
+
+  void set_origin(Flags origin);
+  int  get_origin()             const { return _attr & VALUE_ORIGIN_MASK;        }
+  bool is_default()             const { return (get_origin() == DEFAULT);        }
+  bool is_ergonomic()           const { return (get_origin() == ERGONOMIC);      }
+  bool is_command_line()        const { return (_attr & ORIG_COMMAND_LINE) != 0; }
+
+  void set_command_line()             { _attr |= ORIG_COMMAND_LINE;              }
+
+  bool is_product()             const { return (_attr & IS_PRODUCT) != 0;        }
+  bool is_manageable()          const { return (_attr & MANAGEABLE) != 0;        }
+  bool is_diagnostic()          const { return (_attr & DIAGNOSTIC) != 0;        }
+  bool is_experimental()        const { return (_attr & EXPERIMENTAL) != 0;      }
+  bool is_notproduct()          const { return (_attr & NOT_PRODUCT) != 0;       }
+  bool is_develop()             const { return (_attr & DEVELOP) != 0;           }
+  bool is_read_write()          const { return (_attr & READ_WRITE) != 0;        }
+
+  bool ccstr_accumulates()      const { return is_ccstr() && (_attr & STRINGLIST) != 0; }
+
+  // is this flag a constant in the JVM binary.
+  bool is_constant_in_binary() const {
+    return PRODUCT_ONLY(is_notproduct() || is_develop())
+           NOT_PRODUCT(false);
+  }
+
+  bool is_writeable() const {
+    return is_manageable() || (is_product() && is_read_write());
+  }
+
+  // All flags except "manageable" are assumed to be internal flags.
+  // Long term, we need to define a mechanism to specify which flags
+  // are external/stable and change this function accordingly.
+  bool is_external() const {
+    return is_manageable();
+  }
+
+  static void printAllFlags();
+  const char* type_string() const;
+
+  void set_range(void* range) {
+    assert(_range == NULL, "set only once");
+    assert((_attr & RANGE) != 0, "must be");
+    _range = range;
+  }
+
+  void set_constraint(void* constraint) {
+    assert(_constraint == NULL, "set only once");
+    assert((_attr & CONSTRAINT) != 0, "must be");
+    _constraint = constraint;
+  }
+
+  bool has_range() const { return _range != NULL; }
+  void print_value(outputStream*) const;
+  void print_range(outputStream*) const;
+  JVMFlag::Error check_range(void* new_value, bool verbose) const;
+  JVMFlag::Error check_constraint(void* new_value, bool verbose) const;
+
+  static void validate_flags() PRODUCT_RETURN;
+
+  // Range and constraint checking
+  struct PrintFormat {
+    NOT_PRODUCT(JVMFlag::FlagType type;)
+    const char* print_value_format;
+    const char* range_error_format;
+    const char* print_range_format;
+  };
+
+  static PrintFormat print_formats[]; // This can be changed to a const table with c++11
+  bool is_jimage_resource();
 
-  // points to all Flags static array
-  static JVMFlag* flags;
+  template <typename T> inline void print_range_helper(outputStream* st, T min, T max) const;
+  void print_range_for_constraint(outputStream* st, void* constraint_func) const;
+  void print_attr(outputStream* st, int width) const;
+
+protected:
+  template <typename T> inline void print_range_error(T new_value, T min, T max, bool verbose) const;
+
+  template <typename T> Error check_range_helper(T new_value, T min, T max, bool verbose) const {
+    if ((new_value < min) || (new_value > max)) {
+      print_range_error(new_value, min, max, verbose);
+      return JVMFlag::OUT_OF_BOUNDS;
+    } else {
+      return JVMFlag::SUCCESS;
+    } 
+  }
 
-  // number of flags
-  static size_t numFlags;
+  template <typename T> Error check_constraint_helper(T new_value, void* func, ConstraintPhase phase, bool verbose) const {
+    typedef Error ConstraintFunc(T value, bool verbose);
+    if (phase > _constraint_validating_phase) {
+      // This constraint is for a later phase. Don't call it now.
+      return JVMFlag::SUCCESS;
+    }
+    return ((ConstraintFunc*)func)(new_value, verbose);
+  }
 
 private:
   static JVMFlag* find_flag(const char* name, size_t length, bool allow_locked, bool return_flag);
 
 public:

@@ -133,131 +319,323 @@
     return find_declared_flag(name, strlen(name));
   }
 
   static JVMFlag* fuzzy_match(const char* name, size_t length, bool allow_locked = false);
 
-  static const char* get_int_default_range_str();
-  static const char* get_uint_default_range_str();
-  static const char* get_intx_default_range_str();
-  static const char* get_uintx_default_range_str();
-  static const char* get_uint64_t_default_range_str();
-  static const char* get_size_t_default_range_str();
-  static const char* get_double_default_range_str();
-
-  bool is_bool() const;
-  bool get_bool() const                       { return *((bool*) _addr); }
-  void set_bool(bool value)                   { *((bool*) _addr) = value; }
-
-  bool is_int() const;
-  int get_int() const                         { return *((int*) _addr); }
-  void set_int(int value)                     { *((int*) _addr) = value; }
-
-  bool is_uint() const;
-  uint get_uint() const                       { return *((uint*) _addr); }
-  void set_uint(uint value)                   { *((uint*) _addr) = value; }
-
-  bool is_intx() const;
-  intx get_intx() const                       { return *((intx*) _addr); }
-  void set_intx(intx value)                   { *((intx*) _addr) = value; }
-
-  bool is_uintx() const;
-  uintx get_uintx() const                     { return *((uintx*) _addr); }
-  void set_uintx(uintx value)                 { *((uintx*) _addr) = value; }
-
-  bool is_uint64_t() const;
-  uint64_t get_uint64_t() const               { return *((uint64_t*) _addr); }
-  void set_uint64_t(uint64_t value)           { *((uint64_t*) _addr) = value; }
-
-  bool is_size_t() const;
-  size_t get_size_t() const                   { return *((size_t*) _addr); }
-  void set_size_t(size_t value)               { *((size_t*) _addr) = value; }
-
-  bool is_double() const;
-  double get_double() const                   { return *((double*) _addr); }
-  void set_double(double value)               { *((double*) _addr) = value; }
-
-  bool is_ccstr() const;
-  bool ccstr_accumulates() const;
-  ccstr get_ccstr() const                     { return *((ccstr*) _addr); }
-  void set_ccstr(ccstr value)                 { *((ccstr*) _addr) = value; }
-
-  Flags get_origin();
-  void set_origin(Flags origin);
-
   size_t get_name_length();
 
-  bool is_default();
-  bool is_ergonomic();
-  bool is_jimage_resource();
-  bool is_command_line();
-  void set_command_line();
-
-  bool is_product() const;
-  bool is_manageable() const;
-  bool is_diagnostic() const;
-  bool is_experimental() const;
-  bool is_notproduct() const;
-  bool is_develop() const;
-  bool is_read_write() const;
-
-  bool is_constant_in_binary() const;
-
   bool is_unlocker() const;
   bool is_unlocked() const;
-  bool is_writeable() const;
-  bool is_external() const;
 
   void clear_diagnostic();
   void clear_experimental();
   void set_product();
 
   JVMFlag::MsgType get_locked_message(char*, int) const;
   JVMFlag::MsgType get_locked_message_ext(char*, int) const;
 
   // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
-  void print_on(outputStream* st, bool withComments = false, bool printRanges = false);
-  void print_kind(outputStream* st, unsigned int width);
-  void print_origin(outputStream* st, unsigned int width);
-  void print_as_flag(outputStream* st);
+  void print_on(outputStream* st, bool withComments = false, bool printRanges = false) const;
+  void print_kind(outputStream* st, unsigned int width) const;
+  void print_origin(outputStream* st, unsigned int width) const;
+  void print_as_flag(outputStream* st) const;
 
   static const char* flag_error_str(JVMFlag::Error error);
 
 public:
   static JVMFlag::Error boolAt(const JVMFlag* flag, bool* value);
-  static JVMFlag::Error boolAtPut(JVMFlag* flag, bool* value, JVMFlag::Flags origin);
+  static JVMFlag::Error boolAtPut(JVMFlag* flag, bool value, Attr origin);
 
   static JVMFlag::Error intAt(const JVMFlag* flag, int* value);
-  static JVMFlag::Error intAtPut(JVMFlag* flag, int* value, JVMFlag::Flags origin);
+  static JVMFlag::Error intAtPut(JVMFlag* flag, int value, Attr origin);
 
   static JVMFlag::Error uintAt(const JVMFlag* flag, uint* value);
-  static JVMFlag::Error uintAtPut(JVMFlag* flag, uint* value, JVMFlag::Flags origin);
+  static JVMFlag::Error uintAtPut(JVMFlag* flag, uint value, Attr origin);
 
   static JVMFlag::Error intxAt(const JVMFlag* flag, intx* value);
-  static JVMFlag::Error intxAtPut(JVMFlag* flag, intx* value, JVMFlag::Flags origin);
+  static JVMFlag::Error intxAtPut(JVMFlag* flag, intx value, Attr origin);
 
   static JVMFlag::Error uintxAt(const JVMFlag* flag, uintx* value);
-  static JVMFlag::Error uintxAtPut(JVMFlag* flag, uintx* value, JVMFlag::Flags origin);
+  static JVMFlag::Error uintxAtPut(JVMFlag* flag, uintx value, Attr origin);
 
   static JVMFlag::Error size_tAt(const JVMFlag* flag, size_t* value);
-  static JVMFlag::Error size_tAtPut(JVMFlag* flag, size_t* value, JVMFlag::Flags origin);
+  static JVMFlag::Error size_tAtPut(JVMFlag* flag, size_t value, Attr origin);
 
   static JVMFlag::Error uint64_tAt(const JVMFlag* flag, uint64_t* value);
-  static JVMFlag::Error uint64_tAtPut(JVMFlag* flag, uint64_t* value, JVMFlag::Flags origin);
+  static JVMFlag::Error uint64_tAtPut(JVMFlag* flag, uint64_t value, Attr origin);
 
   static JVMFlag::Error doubleAt(const JVMFlag* flag, double* value);
-  static JVMFlag::Error doubleAtPut(JVMFlag* flag, double* value, JVMFlag::Flags origin);
+  static JVMFlag::Error doubleAtPut(JVMFlag* flag, double value, Attr origin);
 
   static JVMFlag::Error ccstrAt(const JVMFlag* flag, ccstr* value);
   // Contract:  JVMFlag will make private copy of the incoming value.
   // Outgoing value is always malloc-ed, and caller MUST call free.
-  static JVMFlag::Error ccstrAtPut(JVMFlag* flag, ccstr* value, JVMFlag::Flags origin);
+  static JVMFlag::Error ccstrAtPut(JVMFlag* flag, ccstr* value, Attr origin);
+  static JVMFlag::Error ccstrAtPut(JVMFlag* flag, ccstr value, Attr origin) {
+    return ccstrAtPut(flag, &value, origin);
+  }
 
   static void printSetFlags(outputStream* out);
 
   // printRanges will print out flags type, name and range values as expected by -XX:+PrintFlagsRanges
   static void printFlags(outputStream* out, bool withComments, bool printRanges = false, bool skipDefaults = false);
   static void printError(bool verbose, const char* msg, ...) ATTRIBUTE_PRINTF(2, 3);
 
+  static bool check_all_ranges();
+  static bool check_all_constraints(ConstraintPhase phase);
+
   static void verify() PRODUCT_RETURN;
 };
 
+template <typename T> class TypedJVMFlag;
+
+template <typename T> class JVMFlagRange {
+public:
+  T _min;
+  T _max;
+  inline JVMFlagRange(TypedJVMFlag<T>* f, T min, T max);
+
+  void init(T min, T max) {
+    _min = min;
+    _max = max;
+  }
+};
+
+template <typename T> class JVMFlagConstraint {
+public:
+  void* _func;
+  JVMFlag::ConstraintPhase _phase;
+  inline JVMFlagConstraint(TypedJVMFlag<T>* f, void* func, JVMFlag::ConstraintPhase phase);
+};
+
+template <typename T>
+class TypedJVMFlag : public JVMFlag {
+protected:
+  T* value_addr() const {
+    return (T*)_value_addr;
+  }
+
+  const JVMFlagRange<T>* range() const {
+    return (const JVMFlagRange<T>*)_range;
+  }
+  const JVMFlagConstraint<T>* constraint() const {
+    return (const JVMFlagConstraint<T>*)_constraint;
+  }
+
+public:
+  TypedJVMFlag(JVMFlag::FlagType type, const char* name, int attr, 
+               T* value_addr, const char* docs) :
+    JVMFlag(type, name, attr, (void*)value_addr, docs) {}
+
+  static const TypedJVMFlag<T>* cast(const JVMFlag* flag) {
+    return (const TypedJVMFlag<T>*)flag;
+  }
+
+  T get_value() const {
+    return *value_addr();
+  }
+
+  void print_typed_range(outputStream* st) const {
+    if (range() != NULL) {
+      JVMFlag::print_range_helper(st, range()->_min,  range()->_max);
+    } else {
+      assert(constraint() != NULL, "must be");
+      JVMFlag::print_range_for_constraint(st, constraint()->_func);
+    }
+  }
+
+  JVMFlag::Error check_typed_range(void* new_value, bool verbose) const {
+    assert(range() != NULL, "must be");
+    T n = *((T*)new_value);
+    return JVMFlag::check_range_helper(n, range()->_min,  range()->_max, verbose);
+  }
+
+  JVMFlag::Error check_typed_constraint(void* new_value, bool verbose) const {
+    assert(constraint() != NULL, "must be");
+    T n = *((T*)new_value);
+    return check_constraint_helper(n, constraint()->_func, constraint()->_phase, verbose);
+  }
+};
+
+template <typename T>
+inline JVMFlagRange<T>::JVMFlagRange(TypedJVMFlag<T>* f, T min, T max) {
+  _min = min;
+  _max = max;
+  f->set_range(this);
+}
+
+template <typename T>
+inline JVMFlagConstraint<T>::JVMFlagConstraint(TypedJVMFlag<T>* f, void* func, JVMFlag::ConstraintPhase phase) {
+  _func = func;
+  _phase = phase;
+  f->set_constraint(this);
+}
+
+
+template <typename T>
+class ProductFlag : public TypedJVMFlag<T> {
+public:
+  ProductFlag(JVMFlag::FlagType type,  const char* name, int attr,
+              T* value_addr, const char* docs) :
+    TypedJVMFlag<T>(type, name, attr, value_addr, docs) {}
+
+  JVMFlag::Error check_new_value(T new_value, JVMFlag::Attr origin);
+
+  static ProductFlag<T>* cast(JVMFlag* flag) {
+    return (ProductFlag<T>*)flag;
+  }
+
+  void write_value(T value) {
+    *TypedJVMFlag<T>::value_addr() = value;
+  }
+};
+
+#ifdef PRODUCT
+template <typename T>
+class DevelopFlag : public TypedJVMFlag<T> {
+public:
+  DevelopFlag(JVMFlag::FlagType type, const char* name, int attr,
+              const T* value_addr) :
+    TypedJVMFlag<T>(type, name, attr, (T*)value_addr, "") {}
+};
+#endif // PRODUCT (class DevelopFlag)
+
+// The FLAG_COMMON_ATTRS and FLAG_ATTR macros allow you to define a group of flags all with the same
+// common attribute. See globals.hpp.
+#ifndef FLAG_COMMON_ATTRS
+#define FLAG_COMMON_ATTRS 0
+#endif
+#define FLAG_ATTR(attr) (attr | FLAG_COMMON_ATTRS)
+
+// ----- Macros for setting the values of the JVM flags -----
+#define FLAG_STRUCT(name) (FLAG_##name)
+#define FLAG_MEMBER_SET(name) Flag_##name##_set
+
+#define FLAG_IS_DEFAULT(name)         (FLAG_STRUCT(name).is_default())
+#define FLAG_IS_ERGO(name)            (FLAG_STRUCT(name).is_ergonomic())
+#define FLAG_IS_CMDLINE(name)         (FLAG_STRUCT(name).is_command_line())
+#define FLAG_IS_JIMAGE_RESOURCE(name) (FLAG_STRUCT(name).is_jimage_resource())
+
+#define FLAG_SET_DEFAULT(name, value) ((name) = (value))
+
+#define FLAG_SET_CMDLINE(name, value) (FLAG_STRUCT(name).set_command_line(), \
+                                       FLAG_MEMBER_SET(name)(value, JVMFlag::COMMAND_LINE))
+#define FLAG_SET_ERGO(name, value)    (FLAG_MEMBER_SET(name)(value, JVMFlag::ERGONOMIC))
+#define FLAG_SET_MGMT(name, value)    (FLAG_MEMBER_SET(name)(value, JVMFlag::MANAGEMENT))
+
+#define FLAG_SET_ERGO_IF_DEFAULT(name, value) \
+  do {                                        \
+    if (FLAG_IS_DEFAULT(name)) {              \
+      FLAG_SET_ERGO(name, value);             \
+    }                                         \
+  } while (0)
+
+#define JVMFLAG_FOR_EACH(f) \
+  for (f = JVMFlag::head(); f != NULL; f = f->next())
+
+// ---- Macros for declaring VM flags in *globals.hpp files -----
+
+#define ALL_FLAG_COMMON(type, name, attr, docs) \
+  typedef type FLAG_TYPE_##name; \
+  inline JVMFlag::FlagType FLAG_TYPE_NAME_##name() { return JVMFlag::TYPE_##type; } \
+  inline int FLAG_ATTR_##name() { return attr; } \
+  inline const char* FLAG_DOCS_##name() { return docs; }
+
+#define PRODUCT_FLAG_COMMON(type, name, attr, docs) \
+  ALL_FLAG_COMMON(type, name, attr, docs); \
+  extern ProductFlag<FLAG_TYPE_##name> FLAG_##name; \
+  inline JVMFlag::Error FLAG_MEMBER_SET(name)(type value, JVMFlag::Flags origin) { return JVMFlag::type##AtPut(&FLAG_##name, value, origin); } \
+  extern "C" type name
+
+#define PRODUCT_FLAG(type, name, default_value, attr, docs) \
+  inline type FLAG_DEFVAL_##name() { return default_value; } \
+  PRODUCT_FLAG_COMMON(type, name, attr, docs)
+
+#define PRODUCT_FLAG_PD(type, name, attr, docs) \
+  PRODUCT_FLAG_COMMON(type, name, ((attr) | JVMFlag::PLATFORM_DEPENDENT), docs)
+
+#ifdef PRODUCT
+// In product builds, meta information for DEVELOP_FLAG is stored in DevelopFlag<T>
+
+#define DEVELOP_FLAG_COMMON(type, name, attr, docs) \
+  ALL_FLAG_COMMON(type, name, attr, docs); \
+  extern DevelopFlag<FLAG_TYPE_##name> FLAG_##name
+
+#define DEVELOP_FLAG(type, name, default_value, attr, docs) \
+  DEVELOP_FLAG_COMMON(type, name, ((attr) | JVMFlag::DEVELOP), docs); \
+  const type name = default_value
+
+#define DEVELOP_FLAG_PD(type, name, attr, docs) \
+  DEVELOP_FLAG_COMMON(type, name, ((attr) | JVMFlag::DEVELOP | JVMFlag::PLATFORM_DEPENDENT), docs); \
+  const type name = pd_##name
+
+// In product builds, NOTPROD_FLAGs are not visible at all, but we
+// emit a typedef to make the FLAG_RANGE macro happy.
+#define NOTPROD_FLAG(type, name, default_value, attr, docs) \
+  typedef type FLAG_TYPE_##name
+
+#else
+// !defined(PRODUCT)
+
+// In develop builds, DEVELOP_FLAG and NOTPROD_FLAG are equivalent to PRODUCT_FLAG
+#define NOTPROD_FLAG(type, name, default_value, attr, docs) \
+  PRODUCT_FLAG(type, name, default_value, ((attr) | JVMFlag::NOT_PRODUCT) , docs)
+
+#define DEVELOP_FLAG(type, name, default_value, attr, docs) \
+  PRODUCT_FLAG(type, name, default_value, ((attr) | JVMFlag::DEVELOP), docs)
+
+#define DEVELOP_FLAG_PD(type, name, attr, docs) \
+  PRODUCT_FLAG_PD(type, name, ((attr) | JVMFlag::DEVELOP), docs)
+
+#endif // PRODUCT
+
+// ---- Macros for specifying VM flags constraints in *globals.hpp files -----
+
+#define FLAG_RANGE(name, min, max) \
+  inline FLAG_TYPE_##name FLAG_MIN_##name() { return min;} \
+  inline FLAG_TYPE_##name FLAG_MAX_##name() { return max;}
+
+#define FLAG_CONSTRAINT(name, func, phase) \
+  inline void* FLAG_CONSTRAINT_FUNC_##name() { return (void*)func;} \
+  inline JVMFlag::ConstraintPhase FLAG_CONSTRAINT_PHASE_##name() { return phase; }
+
+class JVMFlagCustomRange {
+  JVMFlagCustomRange* _next;
+  static JVMFlagCustomRange* _head;
+
+protected:
+  virtual void init() = 0;
+
+public:
+  JVMFlagCustomRange() {
+    _next = _head;
+    _head = this;
+  }
+  static void init_all() {
+    for (JVMFlagCustomRange* r = _head; r; r = r->_next) {
+      r->init();
+    }
+  }
+};
+
+class JVMFlagRange_VMPageSize : public JVMFlagCustomRange {
+  JVMFlagRange<uintx> _r;
+protected:
+  virtual void init();
+public:
+  JVMFlagRange_VMPageSize(TypedJVMFlag<uintx>* f) :
+    JVMFlagCustomRange(), _r(f, 0, 0) {}
+};
+
+class JVMFlagRange_VMAllocationGranularity :  public JVMFlagCustomRange {
+  JVMFlagRange<size_t> _r;
+protected:
+  virtual void init();
+public:
+  JVMFlagRange_VMAllocationGranularity(TypedJVMFlag<size_t>* f) :
+    JVMFlagCustomRange(), _r(f, 0, 0) {}
+};
+
+#define FLAG_CUSTOM_RANGE(name, which) \
+  typedef JVMFlagRange_##which FLAG_RANGE_TYPE_##name
+
 #endif // SHARE_RUNTIME_FLAGS_JVMFLAG_HPP
< prev index next >