Date: Thu, 28 Mar 2024 09:30:07 +0000 (UTC) Message-ID: <2072309052.1113.1711618207802@34fc92c9345b> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_1112_369428189.1711618207801" ------=_Part_1112_369428189.1711618207801 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
Note: this proposal has bee= n withdrawn. It has been superceded by JDK-= 8243208
This is a design document for JDK-8236988 - M= odular Design for JVM Flags
Improve the implementation of JVM command-line flags (such as -XX:+U= seCompressedOops)
Break up monolithic globals.hpp
#include "gc/z/z_global=
s.hpp
"
#include "memory/metaspaceShared_globals.hpp" // just <=
a class=3D"external-link" href=3D"http://hg.openjdk.java.net/jdk/jdk/file/5=
ac19bd3a1e2/src/hotspot/share/runtime/globals.hpp#l2257" rel=3D"nofollow">f=
lags related to CDS
E.g., one can have a "manageable" switch and an "experimental" switc= h, but not a "manageable_experimental" switch.
(Design contribution by Erik =C3=96sterlund, Stefan Karlsson, = Coleen Phillimore)
NOTE:
Before
product()
, devel=
op()
, diagnostic()
, etc.produc= t(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.// PROD= UCT_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 eq= ual 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*)InteriorEntryAlignmen= tConstraintFunc, 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::EXP= ERIMENTAL, 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 c= ode can use it // to dynamically query the type of this flag. extern ProductFlag<FLAG_TYPE_StressLCM> FLAG_StressLCM;=20 // 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 sc= heduling 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 info=
rmation between the HPP and CPP files, so the CPP files contains just boile=
rplate code.
DEFN_PR= ODUCT_FLAG(StressLCM); DEFN_PRODUCT_FLAG(StressGCM); DEFN_PRODUCT_FLAG(MaxLoopPad); DEFN_PRODUCT_RANGE(MaxLoopPad); DEFN_PRODUCT_FLAG_PD(InteriorEntryAlignment); DEFN_PRODUCT_CONSTRAINT(Inter= iorEntryAlignment);
Macros in the CPP files are expanded to
// Defi= nition of the flag itself FLAG_TYPE_StressLCM StressLCM =3D 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 register= s // itself as the range spec for FLAG_MaxLoopPad,=20 FLAG_MaxLoopPad._range =3D &FLAG_RANGE_MaxLoopPad;
The consistency between the .hpp/.cpp files are mostly sta=
tically enforced at compile time. E.g.,
However, it's possible to forget to put DEFN_PRODUCT_RANGE(MaxLoop=
Pad)
in c2_globals.cpp. I can't think of a way to static=
ally 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 stor=
ed in the structure FLAG_XYZ
. This structure can be used direc=
tly to access the flag. E.g.,
intx ne= w_val =3D .....; FLAG_MaxLoopPad.check_range(&new_val, verbose);
As a result, we no longer need to do a linear search for range/constrain= t checking.
Iterating over all flags:
The FLAG_XXXs are constructed using C++ global constructors, and are app=
ended to a global list. This list can be used for iterating over all the fl=
ags (e.g., for implementing -XX:+PrintFlagsFinal
).
struct = JVMFlag { static JVMFlag* _head; JVMFlag* _next; ...=20 }; =20 template <typename T> class ProductFlag : /* a subclass of JVMFlag */ { ProductFlagNone(...) { /*effectively*/ this->_next =3D _head; // executed as C++ global constructor _head =3D this; }}; =20 #define JVMFLAG_FOR_EACH(f) \ for (f =3D JVMFlag::head(); f !=3D NULL; f =3D f->next())
Alternatives
flag type =3D bool, name =3D UseCompressedOops, default =3D false, h= elp =3D "Use 32-bit object references in 64-bit VM.", type =3D product | lp= 64;
Or XML, or ....
Auto-generation of header files from templates