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

    Loading...
  1. Dashboard
  2. Undefined Space
  3. HotSpot
  4. Hotspot Command-line Flags Clean Up - Design Proposal for JDK-8243208

Page History

Versions Compared

Old Version 4

changes.mady.by.user Ioi Lam

Saved on Sep 01, 2020

compared with

New Version 5

changes.mady.by.user Ioi Lam

Saved on Sep 01, 2020

  • Previous Change: Difference between versions 3 and 4
  • Next Change: Difference between versions 5 and 6
  • View Page History

Key

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

...

The new design (see here for webrev):

  • Builds the checker objects (JVMFlagLimit) at build-time using constexpr.
  • JVMFlagLimit objects are indexed by each flag's enum (or NULL if no limit exists), so it's O(1) time.

Implementation of JVMFlagLimit

The range/constraint information for a flag of type T is described by a JVMTypedFlagLimit<T>:

Code Block
class JVMFlagLimit {
  enum {
    HAS_RANGE = 1,
    HAS_CONSTRAINT = 2
  };

  short _constraint_func;   
  char  _phase;
  char  _kind; ...};


template <typename T>
class JVMTypedFlagLimit : public JVMFlagLimit {
  const T _min;        
  const T _max; ...};

Each flag is given a unique enum that starts from 0 to NUM_JVMFlagsEnum-1. We use this enum to find the JVMTypedFlagLimit<T> of this flag from an array:

Code Block
static constexpr const JVMFlagLimit* const flagLimitTable[1 + NUM_JVMFlagsEnum] = { .... }
const JVMFlagLimit* const* JVMFlagLimit::flagLimits = &flagLimitTable[1]; // excludes dummy

/* E.g., to get the limit of this flag:
  product(intx, ContendedPaddingWidth, 128,                                 \
          "How many bytes to pad the fields/classes marked @Contended with")\
          range(0, 8192)                                                    \
          constraint(ContendedPaddingWidthConstraintFunc,AfterErgo)         \
*/
const JVMTypedFlagLimit<intx>* limit = JVMFlagLimit::flagLimits[Flag_ContendedPaddingWidth_Enum];


// We have will see these fields:
// limit->_constraint_func   ==> constraint_enum_ContendedPaddingWidthConstraintFunc  (more on this below)
// limit->_phase             ==> AfterErgo
// limit->_kind              ==> HAS_RANGE | HAS_CONSTRAINT
// limit->_min               ==> 0
// limit->_max               ==> 8192

...

To do this, we first define a JVMTypedFlagLimit<T> variable for each flag (including the ones that don't have range/constraint). It's done by this macro:

Code Block
//           macro body starts here -------------------+
//                                                     |
//                                                     v
#define FLAG_LIMIT_DEFINE(      type, name, ...)       ); const JVMTypedFlagLimit<type> limit_##name(0
#define FLAG_LIMIT_DEFINE_DUMMY(type, name, ...)       ); const DummyLimit nolimit_##name(0
#define FLAG_LIMIT_PTR(         type, name, ...)       ), LimitGetter<type>::get_limit(&limit_##name, 0
#define FLAG_LIMIT_PTR_NONE(    type, name, ...)       ), LimitGetter<type>::no_limit(0
#define APPLY_FLAG_RANGE(...)                          , __VA_ARGS__
#define APPLY_FLAG_CONSTRAINT(func, phase)             , next_two_args_are_constraint, (short)CONSTRAINT_ENUM(func), int(JVMFlagConstraint::phase)

constconstexpr JVMTypedFlagLimit<int> limit_dummy
(
#ifdef PRODUCT
 ALL_FLAGS(FLAG_LIMIT_DEFINE_DUMMY,
           FLAG_LIMIT_DEFINE_DUMMY,
           FLAG_LIMIT_DEFINE,
           FLAG_LIMIT_DEFINE,
           FLAG_LIMIT_DEFINE_DUMMY,
           APPLY_FLAG_RANGE,
           APPLY_FLAG_CONSTRAINT)
#else
 ALL_FLAGS(FLAG_LIMIT_DEFINE,
           FLAG_LIMIT_DEFINE,
           FLAG_LIMIT_DEFINE,
           FLAG_LIMIT_DEFINE,
           FLAG_LIMIT_DEFINE,
           APPLY_FLAG_RANGE,
           APPLY_FLAG_CONSTRAINT)
#endif
);

To understand how this worksthe macros work, it's best to compile jvmFlagLimit.c with gcc -save-temps. and look at the generated jvmFlagLimit.ii with the macros expanded. Here's an example:

...

 (prettified manually):

Code Block
constexpr JVMTypedFlagLimit<int>  limit_dummy();
constexpr JVMTypedFlagLimit<bool> limit_UseCompressedOops(0);
....
constexpr JVMTypedFlagLimit<intx> limit_ObjectAlignmentInBytes(0, 8, 256,
             next_two_args_are_constraint,
            (short)constraint_enum_ObjectAlignmentInBytesConstraintFunc, int(JVMFlagConstraint::AtParse));
....
constexpr JVMTypedFlagLimit<intx> limit_JVMCIThreads(0, 1, max_jint);

We use overloaded constructors to fill out the necessarily fields of the JVMTypedFlagLimit<T> variables. Note that the min/max parameters, as well as the constraint_func/phase parameters, can both be integer values. For disambiguation, we pass in a dummy next_two_args_are_constraint for the constraint_func/phase.

We also need to always pass in an initial dummy 0 parameter so that the macros can safely add a comma before passing the min/max or constraint_func/phase.

These dummy parameters are evaluated at compile time so they can be safely optimized away.

The next step is to fill out the flagLimitTable[] array:

Code Block
static constexpr const JVMFlagLimit* const flagLimitTable[1 + NUM_JVMFlagsEnum] = {
  // Because FLAG_LIMIT_PTR must start with an "),", we have to place a dummy element here.
  LimitGetter<int>::get_limit(NULL, 0

#ifdef PRODUCT
  ALL_FLAGS(FLAG_LIMIT_PTR_NONE,
            FLAG_LIMIT_PTR_NONE,
            FLAG_LIMIT_PTR,
            FLAG_LIMIT_PTR,
            FLAG_LIMIT_PTR_NONE,
            APPLY_FLAG_RANGE,
            APPLY_FLAG_CONSTRAINT)
#else
  ALL_FLAGS(FLAG_LIMIT_PTR,
            FLAG_LIMIT_PTR,
            FLAG_LIMIT_PTR,
            FLAG_LIMIT_PTR,
            FLAG_LIMIT_PTR,
            APPLY_FLAG_RANGE,
            APPLY_FLAG_CONSTRAINT)
#endif
  )
};

For the flags shown in the example above, the following code is generated by the macros:

Code Block
static constexpr const JVMFlagLimit* const flagLimitTable[1 + NUM_JVMFlagsEnum] = {
  LimitGetter<int>::get_limit(NULL, 0),
  LimitGetter<bool>::get_limit(&limit_UseCompressedOops, 0),
  ....
  LimitGetter<intx>::get_limit(&limit_ObjectAlignmentInBytes, 0,
             8, 256,
             next_two_args_are_constraint,
            (short)constraint_enum_ObjectAlignmentInBytesConstraintFunc, int(JVMFlagConstraint::AtParse)),
  ....
  LimitGetter<intx>::get_limit(&limit_JVMCIThreads, 0, 1, max_jint),
  • If a flag has neither range nor constraint, we will call the LimitGetter<T>::get_limit() function with two parameters, which returns NULL.
  • If a flag has range and/or constraint, we will call a  LimitGetter<T>::get_limit() function with more than two parameters. These functions would return the same JVMTypedFlagLimit<T> as passed in.

As a result, we will end up with this in the final output of the C++ compiler:

Code Block
static constexpr const JVMFlagLimit* const flagLimitTable[1 + NUM_JVMFlagsEnum] = {
  NULL, // dummy
  NULL, // UseCompressedOops has no range/constraint
  ....
  &limit_ObjectAlignmentInBytes
  ....
  &limit_JVMCIThreads

What happens to unreferenced flag limits

All the flag limits are defined with the constexpr keyword, which has internal linkage by default. If a flag has no range/constraint, its flag limit (e.g., limit_UseCompressedOops in the example above) will be unused, and will be eliminated by the C++ compiler from the object file. So we don't waste any space.

Why use enums for constraint_func

This is a small optimization: There are 120 flags that use a constraint function, but there are only 65 total constraint functions. By using a short index, we can:

  • Reduce the size of the JVMFlagLimit object (the 2 bytes fits in unused space)
  • Reduce the number of pointers relocated when libjvm.so is dynamically loaded (from 120 to 65).

The savings are not a big deal, but since we can do it, why not?

...

Is constexpr really working?

...

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.23
  • Kolekti ThemeBuilder printed.by.atlassian.confluence
  • Report a bug
  • Atlassian News
Atlassian
Kolekti ThemeBuilder EngineAtlassian Confluence
{"serverDuration": 469, "requestCorrelationId": "a81812dbf889d99c"}