This document describes ....Latest Webrev: http://cr.openjdk.java.net/~iklam/jdk16/8243208-cleanup-jvmflag-impl.v00/
Goals
- Reduce the complexity of macros related to command-line flags (JDK-82432098243208)
- Avoid including large globals.hpp in every file. Just include the <mod>_globals.hpp file of the module you need (separate RFE: JDK-8243205)
- Improvement footprint/performance
Non Goals
- The flag declaration is done with large X-macros. Although some people find this objectionably, this proposal does not change that.
Requirements for Command-line Flags
...
Code Block |
---|
#define RUNTIME_FLAGS(develop, \ develop_pd, \ product, \ product_pd, \ /* REMOVED diagnostic, */\ /* REMOVED diagnostic_pd, */ \ /* REMOVED experimental, */\ notproduct, \ /* REMOVED manageable, */ \ /* REMOVED product_rw, */\ /* REMOVED lp64_product, */\ range, \ constraint) \ ..... develop(bool, CleanChunkPoolAsync, true, /* no attr */ \ "Clean the chunk pool asynchronously") \ \ product(uint, HandshakeTimeout, 0, /* attr= */DIAGNOSTIC, \ "If nonzero set a timeout in milliseconds for handshakes") \ \ product(bool, AlwaysSafeConstructors, false, /* attr= */ EXPERIMENTAL, \ "Force safe construction, as if all fields are final.") .... |
The flags metadata is defined using overloaded constructors (around lin 679 of jvmFlag.cpp)
Code Block |
---|
constexpr JVMFlag::JVMFlag(int flag_enum, const char* type, const char* name, size_t name_len, void* addr, int extra_flags, int flagsattrs, const char* doc) : _type(type), _name(name), _addr(addr), NOT_PRODUCT_ARG(COMMA _doc(doc)) {} _flags(Flags(flags | extra_flags | DEFAULT | flag_group(flag_enum))), _name_len(name_len) {} constexpr JVMFlagconstexpr JVMFlag::JVMFlag(int flag_enum, const char* type, const char* name, size_t name_len, void* addr, int extra_flags, const char* const char* doc) : JVMFlag(flag_enum, type, name, name_len, addr, extra_flags, /*flagsattrs*/0, doc) {} .... #define DEVELOP_FLAG_INIT( type, name, value, ...) JVMFlag(FLAG_MEMBER_ENUM(name), ...snip..., __VA_ARGS__), #define DEVELOP_FLAG_INIT_PD(type, name, ...) JVMFlag(FLAG_MEMBER_ENUM(name), ...snip..., __VA_ARGS__), ...snip.... static JVMFlag flagTable[1 + NUM_JVMFlagsEnum + 1] = { ...... ALL_FLAGS(DEVELOP_FLAG_INIT, DEVELOP_FLAG_INIT_PD, PRODUCT_FLAG_INIT, PRODUCT_FLAG_INIT_PD, NOTPROD_FLAG_INIT, IGNORE_RANGE, IGNORE_CONSTRAINT) .... // NOTE: ALL_FLAGS() calls RUNTIME_FLAGS() |
...
- Builds list of range/constraint checking objects at VM start-up (lots of code and slow start)
- Range/constraint checking needs linear search (further slows down start-up)
The new code (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.
Is constexpr really working?
If your constexpr's are too complex, the C compiler may decide to generate runtime code (instead of generating the data that your constexpr's compute). A good way to A good way to check is to build the .o with something like "gcc -save-temps" and look at the .s file. Here's an example of jvmFlagLimit.s. The following is the C++ global constructor section. It's very small, so it's good.
Code Block |
---|
_GLOBAL__sub_I_jvmFlagLimit.cpp:
.LFB6450:
.cfi_startproc
pxor %xmm0, %xmm0
movaps %xmm0, 1776+_ZL14flagLimitTable(%rip)
movaps %xmm0, 1792+_ZL14flagLimitTable(%rip)
movaps %xmm0, 1808+_ZL14flagLimitTable(%rip)
movaps %xmm0, 1824+_ZL14flagLimitTable(%rip)
ret
.cfi_endproc
.LFE6450:
.size _GLOBAL__sub_I_jvmFlagLimit.cpp, .-_GLOBAL__sub_I_jvmFlagLimit.cpp
.section .init_array,"aw"
.align 8
.quad _GLOBAL__sub_I_jvmFlagLimit.cpp |
The content of the flagLimitTable is completely determined at build time (except for the 4 slots above which are null'ed at runtime. I don't know why.
You can see that the content of the flagLimitTable is also completely determined at build time (it's in the "ro" section):
Code Block |
---|
.section .data.rel.ro.local,"aw"
.align 32
.type _ZL14flagLimitTable, @object
.size _ZL14flagLimitTable, 9728
_ZL14flagLimitTable: |
Code Block |
.section .data.rel.local .align 32 .type _ZL14flagLimitTable, @object .size _ZL14flagLimitTable, 9728 _ZL14flagLimitTable: .quad 0 .quad 0 .quad 0 .quad _ZL28limit_ObjectAlignmentInBytes .quad 0 .quad 0 .quad 0 .quad 0 .quad 0 .quad 0 .quad 0 .quad _ZL18limit_JVMCIThreads0 .quad _ZL22limitZL28limit_JVMCIHostThreadsObjectAlignmentInBytes .quad _ZL24limit_JVMCIEventLogLevel0 .quad _ZL21limit_JVMCITraceLevel0 .quad _ZL22limit_JVMCICounterSize0 .quad 0 .quad 0 .quad _ZL27limit_JVMCINMethodSizeLimit0 .quad 0 .quad 0_ZL18limit_JVMCIThreads .quad 0 .quad 0 _ZL22limit_JVMCIHostThreads .... |