• Home
    • View
    • Login
    This page
    • Normal
    • Export PDF
    • Page Information

    Loading...
  1. Dashboard
  2. Undefined Space
  3. HotSpot
  4. HotSpot Command-Line Flags Overhaul - Design Doc

Page History

Versions Compared

Old Version 2

changes.mady.by.user Ioi Lam

Saved on Apr 08, 2020

compared with

New Version 3

changes.mady.by.user Ioi Lam

Saved on Apr 08, 2020

  • Previous Change: Difference between versions 1 and 2
  • Next Change: Difference between versions 3 and 4
  • View Page History

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Improve the implementation of JVM command-line flags (such as -XX:+UseCompressedOops)

  • Break up monolithic globals.hpp

    • No need to include all flags for GC, C1, C2, JVMCI, .....

    • Before:
      • #include "runtime/globals.hpp" + globals_shared.hpp  = declare all possible flags
    • After:
      • #include "gc/z/z_globals.hpp" (see also gc/z/z_globals.flags.hpp)
    • Future: subdivide globals.hpp into individual components:
      • (Not in this patch, but possible)
      • #include "memory/metaspaceShared_globals.hpp" (just flags related to CDS).
  • Remove complex macros for flags manipulation
    • Example: jvmFlags.cpp, globals_extension.hpp, jvmFlagRangeList.cpp
  • Hotspot command line switches should have multiple type attributes
    • See JDK-7123237
      • E.g., one can have a "manageable" switch and an "experimental" switch, but not a "manageable_experimental" switch.

  • Templatize duplicated flag processing code:
    • E.g., .(link to attachment)jvmFlags.cpp
  • Speed up range/constraint checking for flags
    • Avoid linear search for every -XX:NumericFlag=value argument in the command-line (jvmFlagRangeList.cpp)

...

  • Most of the current patch is generated by a script, so it's easy to change the design
  • Summary of changes: 14748 14333 lines changed: 6837 6443 ins; 6204 5024 del; 1707 2866 mod; 33867 unchg

Before

  • 34730 unchg

Before


  • Flags are specified via macros like product(), develop(), diagnostic(), etc.
Code Block
 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

  • Flags are specified using a pair of files xxx_globals.hpp, xxx_globals.cpp
  • The HPP file is the "declaration" of the flags. It has a description of all the features for each flag.
    • HotSpot developers should consult the HPP for information about the flags (same as before).

  • Example: c2_globals.hpp:
    • Syntax of the XXX_FLAG macros: see the top of globals.hpp.
    • Implementation of these macros: see jvmFlags.hpp (around line 537)
Code Block
// 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

Code Block
// 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:

Code Block
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

Code Block
FLAG_TYPE_StressLCM StressLCM = FLAG_DEFVAL_StressLCM();


ProductFlag<FLAG_TYPE_StressLCM> FLAG_StressLCM(
    FLAG_TYPE_NAME_StressLCM(),
    "StressLCM",
    (FLAG_ATTR_StressLCM() | JVMFlag::C2),
    &StressLCM, FLAG_DOCS_StressLCM());

// 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.,

  • It's impossible to set a different default or range than as specified in the HPP file.
  • It's impossible to define StressLCM as a different type than declared in the HPP file.

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.,

Code Block
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).

Code Block
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 = 

Declaration Example: c2_globals.hpp (macros such as PRODUCT_FLAG are defined in jvmFlag.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
 
// mode      type     name              def-value     kind
PRODUCT_FLAG(bool,    StressLCM,        false,        None);
DEVELOP_FLAG(intx,    OptoPrologueNops, 0,            Range);
NOTPROD_FLAG(bool,    VerifyGraphEdges, false,        None);
PRODUCT_FLAG(intx,    MaxLoopPad,       (OptoLoopAlignment-1), Range);
 
// def-value is pd_InteriorEntryAlignment (defined in cpu/<arch>/c2_globals_<arch>.hpp
PRODUCT_FLAG_PD(intx, InteriorEntryAlignment,         Constraint);

Macros are expanded to

extern bool StressLCM;
const bool FLAG_DEFVAL_StressLCM = false;
extern ProductFlagNone<bool> FLAG_StressLCM;  // meta-info about the flag
 
extern intx MaxLoopPad;
const intx FLAG_DEFVAL_MaxLoopPad = (OptoLoopAlignment-1);
extern ProductFlagRange<intx> FLAG_MaxLoopPad;
 
extern intx OptoPrologueNops;    // debug build
const intx OptoPrologueNops = 0; // product build
 
extern bool VerifyGraphEdges;    // debug build ONLY

Definition Example: c2_globals.cpp (macros such as DEFN_PRODUCT_FLAG are defined jvmFlag.inline.hpp)

DEFN_PRODUCT_FLAG(bool,   StressLCM, None, JVMFlag::DIAGNOSTIC,
                  "Randomize instruction scheduling in LCM");
DEFN_DEVELOP_FLAG(intx,   OptoPrologueNops, Range, 0,
                 "Insert this many extra nop instructions "
                 "in the prologue of every nmethod",
                 /* range */ 0, 128);
DEFN_PRODUCT_FLAG_PD(intx,   InteriorEntryAlignment, Constraint, 0,
                 "Code alignment for interior entry points "
                 "in generated code (in bytes)",
                 /* constraint */ (void*)InteriorEntryAlignmentConstraintFunc, JVMFlag::AfterErgo);

Macros are expanded to

bool StressLCM = FLAG_DEFVAL_StressLCM;
ProductFlagNone<bool> FLAG_StressLCM(
    JVMFlag::TYPE_bool,
    "StressLCM",                         // name of this flag (for parsing "-XX:+StressLCM")
    (JVMFlag::DIAGNOSTIC | JVMFlag::C2),
    &StressLCM,                          // addr to use for setting flag
    "Randomize .... in LCM");            // help string
 
ProductFlagRange<intx> FLAG_MaxLoopPad(
    JVMFlag::TYPE_intx, "MaxLoopPad",
    (0 | JVMFlag::C2), &MaxLoopPad,
    "Align a loop if padding size ......",
    0, max_jint)                          // range min/max

Iterating over all flags:

...

f->next())


Alternatives

  • Declare flags in template files with custom syntax
    • 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

  • Pros:
    • Can generate more compact code that current proposal (see below)
    • Flags can be pre-sorted, hashed, etc
  • Cons:
    • More complex build (nowhere as bad as .ad files, but affects all developers, not just JIT compiler geeks)
    • Not understood by IDE tools
Overview
Content Tools
ThemeBuilder

Terms of Use
• License: GPLv2
• Privacy • Trademarks • Contact Us

Powered by a free Atlassian Confluence Open Source Project License granted to https://www.atlassian.com/software/views/opensource-community-additional-license-offer. Evaluate Confluence today.

  • Kolekti ThemeBuilder Powered by Atlassian Confluence 8.5.21
  • Kolekti ThemeBuilder printed.by.atlassian.confluence
  • Report a bug
  • Atlassian News
Atlassian
Kolekti ThemeBuilder EngineAtlassian Confluence
{"serverDuration": 575, "requestCorrelationId": "73ca400eeec3251e"}