- Loading...
This is a design document for JDK-8236988 - VM flags: replace ALL_FLAGS macro with a modular design
Improve the implementation of JVM command-line flags (such as -XX:+UseCompressedOops)
Break up monolithic globals.hpp
E.g., one can have a "manageable" switch and an "experimental" switch, but not a "manageable_experimental" switch.
(Design contribution by Erik Österlund, Stefan Karlsson, Coleen Phillimore)
NOTE:
Before
product(), develop(), diagnostic(), etc. product(intx, MaxLoopPad, (OptoLoopAlignment-1), \
"Align a loop if padding size in bytes is less or equal to this " \
"value") \
range(0, max_jint) \
\
develop(intx, OptoPrologueNops, 0, \
"Insert this many extra nop instructions " \
"in the prologue of every nmethod") \
range(0, 128) \
\
notproduct(bool, VerifyGraphEdges , false, \
"Verify Bi-directional Edges") \
\
product_pd(intx, InteriorEntryAlignment, \
"Code alignment for interior entry points " \
"in generated code (in bytes)") \
constraint(InteriorEntryAlignmentConstraintFunc, AfterErgo) \
\
diagnostic(bool, StressLCM, false, \
"Randomize instruction scheduling in LCM") \
After
HotSpot developers should consult the HPP for information about the flags (same as before).
XXX_FLAG macros: see the top of globals.hpp.// PRODUCT_FLAG -- always settable
// DEVELOP_FLAG -- settable only during development and are constant in the PRODUCT version
// NOTPROD_FLAG -- settable only during development and are *not* declared in the PRODUCT version
PRODUCT_FLAG(intx, MaxLoopPad, (OptoLoopAlignment-1), JVMFlag::RANGE,
"Align a loop if padding size in bytes is less or equal to this "
"value");
FLAG_RANGE( MaxLoopPad, 0, max_jint);
DEVELOP_FLAG(intx, OptoPrologueNops, 0, JVMFlag::RANGE,
"Insert this many extra nop instructions "
"in the prologue of every nmethod");
FLAG_RANGE( OptoPrologueNops, 0, 128);
NOTPROD_FLAG(bool, VerifyGraphEdges, false, JVMFlag::DEFAULT,
"Verify Bi-directional Edges");
PRODUCT_FLAG_PD(intx, InteriorEntryAlignment, JVMFlag::CONSTRAINT,
"Code alignment for interior entry points "
"in generated code (in bytes)");
FLAG_CONSTRAINT( InteriorEntryAlignment, (void*)InteriorEntryAlignmentConstraintFunc, JVMFlag::AfterErgo);
// NOTE: diagnostic macros are specified by setting the JVMFlag::DIAGNOSTIC bit in the
// flag's attr (see globals.hpp for details).
//
// This allows more flexible specification of attributes. E.g., manageable-experimental flags
// in JDK-7123237 can be specified using JVMFlag::MANAGEABLE | JVMFlag::EXPERIMENTAL,
PRODUCT_FLAG(bool, StressLCM, false, JVMFlag::DIAGNOSTIC,
"Randomize instruction scheduling in LCM");
Macros in the HPP files are expanded to
// The is the main API of this flag for HotSpot code. E.g.,
// if (StressLCM) {.....}
extern "C" bool StressLCM;
// This structure has the meta-information about this flag. E.g., HotSpot code can use it
// to dynamically query the type of this flag.
extern ProductFlag<FLAG_TYPE_StressLCM> FLAG_StressLCM;
// The following inline functions pass meta-information about this flag to the CPP file
inline bool FLAG_DEFVAL_StressLCM() { return false; }
typedef bool FLAG_TYPE_StressLCM;
inline JVMFlag::FlagType FLAG_TYPE_NAME_StressLCM() { return JVMFlag::TYPE_bool; }
inline int FLAG_ATTR_StressLCM() { return JVMFlag::DIAGNOSTIC; }
inline const char* FLAG_DOCS_StressLCM() { return "Randomize instruction scheduling in LCM"; };
<... the expansion of some macros are omitted for clarity>
// Range information are expanded like this:
inline int FLAG_ATTR_MaxLoopPad() { return JVMFlag::RANGE; }
inline FLAG_TYPE_MaxLoopPad FLAG_MIN_MaxLoopPad() { return 0; }
inline FLAG_TYPE_MaxLoopPad FLAG_MAX_MaxLoopPad() { return max_jint; }
The main goal of the inline functions is to avoid duplicating the information between the HPP and CPP files, so the CPP files contains just boilerplate code.
DEFN_PRODUCT_FLAG(StressLCM); DEFN_PRODUCT_FLAG(StressGCM); DEFN_PRODUCT_FLAG(MaxLoopPad); DEFN_PRODUCT_RANGE(MaxLoopPad); DEFN_PRODUCT_FLAG_PD(InteriorEntryAlignment); DEFN_PRODUCT_CONSTRAINT(InteriorEntryAlignment);
Macros in the CPP files are expanded to
// Definition of the flag itself
FLAG_TYPE_StressLCM StressLCM = FLAG_DEFVAL_StressLCM();
// Definition of the flag's meta information
ProductFlag<FLAG_TYPE_StressLCM> FLAG_StressLCM(
FLAG_TYPE_NAME_StressLCM(),
"StressLCM",
(FLAG_ATTR_StressLCM() | JVMFlag::C2),
&StressLCM, FLAG_DOCS_StressLCM());
<... the expansion of some macros are omitted for clarity>
// Range check is implemented like this
JVMFlagRange<FLAG_TYPE_MaxLoopPad> FLAG_RANGE_MaxLoopPad(
&FLAG_MaxLoopPad, FLAG_MIN_MaxLoopPad(), FLAG_MAX_MaxLoopPad());
// Inside the constructor of FLAG_RANGE_MaxLoopPad, it essentially registers
// itself as the range spec for FLAG_MaxLoopPad,
FLAG_MaxLoopPad._range = &FLAG_RANGE_MaxLoopPad;
The consistency between the .hpp/.cpp files are mostly statically enforced at compile time. E.g.,
However, it's possible to forget to put DEFN_PRODUCT_RANGE(MaxLoopPad) in c2_globals.cpp. I can't think of a way to statically check for that, so I added a runtime check (debug builds only). See JVMFlag::validate_flags().
Meta-information of the flags
As seen above, meta-information about each flag XYZ is stored in the structure FLAG_XYZ. This structure can be used directly to access the flag. E.g.,
intx new_val = .....; FLAG_MaxLoopPad.check_range(&new_val, verbose);
As a result, we no longer need to do a linear search for range/constraint checking.
Iterating over all flags:
The FLAG_XXXs are constructed using C++ global constructors, and are appended to a global list. This list can be used for iterating over all the flags (e.g., for implementing -XX:+PrintFlagsFinal).
struct JVMFlag {
static JVMFlag* _head;
JVMFlag* _next;
...
};
template <typename T>
class ProductFlag : /* a subclass of JVMFlag */ {
ProductFlagNone(...) {
/*effectively*/
this->_next = _head; // executed as C++ global constructor
_head = this;
}};
#define JVMFLAG_FOR_EACH(f) \
for (f = JVMFlag::head(); f != NULL; f = f->next())
Alternatives
flag type = bool, name = UseCompressedOops, default = false, help = "Use 32-bit object references in 64-bit VM.", type = product | lp64;
Or XML, or ....
Auto-generation of header files from templates