--- old/src/hotspot/share/runtime/flags/jvmFlag.hpp 2020-04-05 21:35:22.171108068 -0700 +++ new/src/hotspot/share/runtime/flags/jvmFlag.hpp 2020-04-05 21:35:21.823094968 -0700 @@ -34,8 +34,10 @@ 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, @@ -50,27 +52,35 @@ 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, @@ -106,18 +116,194 @@ 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; + } - // points to all Flags static array - static JVMFlag* flags; + 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(); + + template 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 inline void print_range_error(T new_value, T min, T max, bool verbose) const; + + template 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 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); @@ -135,76 +321,10 @@ 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(); @@ -214,42 +334,45 @@ 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); @@ -257,7 +380,262 @@ 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 class TypedJVMFlag; + +template class JVMFlagRange { +public: + T _min; + T _max; + inline JVMFlagRange(TypedJVMFlag* f, T min, T max); + + void init(T min, T max) { + _min = min; + _max = max; + } +}; + +template class JVMFlagConstraint { +public: + void* _func; + JVMFlag::ConstraintPhase _phase; + inline JVMFlagConstraint(TypedJVMFlag* f, void* func, JVMFlag::ConstraintPhase phase); +}; + +template +class TypedJVMFlag : public JVMFlag { +protected: + T* value_addr() const { + return (T*)_value_addr; + } + + const JVMFlagRange* range() const { + return (const JVMFlagRange*)_range; + } + const JVMFlagConstraint* constraint() const { + return (const JVMFlagConstraint*)_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* cast(const JVMFlag* flag) { + return (const TypedJVMFlag*)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 +inline JVMFlagRange::JVMFlagRange(TypedJVMFlag* f, T min, T max) { + _min = min; + _max = max; + f->set_range(this); +} + +template +inline JVMFlagConstraint::JVMFlagConstraint(TypedJVMFlag* f, void* func, JVMFlag::ConstraintPhase phase) { + _func = func; + _phase = phase; + f->set_constraint(this); +} + + +template +class ProductFlag : public TypedJVMFlag { +public: + ProductFlag(JVMFlag::FlagType type, const char* name, int attr, + T* value_addr, const char* docs) : + TypedJVMFlag(type, name, attr, value_addr, docs) {} + + JVMFlag::Error check_new_value(T new_value, JVMFlag::Attr origin); + + static ProductFlag* cast(JVMFlag* flag) { + return (ProductFlag*)flag; + } + + void write_value(T value) { + *TypedJVMFlag::value_addr() = value; + } +}; + +#ifdef PRODUCT +template +class DevelopFlag : public TypedJVMFlag { +public: + DevelopFlag(JVMFlag::FlagType type, const char* name, int attr, + const T* value_addr) : + TypedJVMFlag(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_##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 + +#define DEVELOP_FLAG_COMMON(type, name, attr, docs) \ + ALL_FLAG_COMMON(type, name, attr, docs); \ + extern DevelopFlag 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 _r; +protected: + virtual void init(); +public: + JVMFlagRange_VMPageSize(TypedJVMFlag* f) : + JVMFlagCustomRange(), _r(f, 0, 0) {} +}; + +class JVMFlagRange_VMAllocationGranularity : public JVMFlagCustomRange { + JVMFlagRange _r; +protected: + virtual void init(); +public: + JVMFlagRange_VMAllocationGranularity(TypedJVMFlag* 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