RFR: 8288477: nmethod header size reduction [v3]
Tom Rodriguez
never at openjdk.org
Thu Jul 21 18:29:11 UTC 2022
On Wed, 13 Jul 2022 20:39:55 GMT, Boris Ulasevich <bulasevich at openjdk.org> wrote:
>> Each compiled method contains an nmethod header. In trivial case, the header takes up half the method payload: ~350 bytes. Over time, the header gets bigger. With this change, I suggest sorting the header data fields from largest to smallest to minimize header paddings, and using one byte for the CompilerType and CompLevel values.
>>
>> Cleanup work: apply CompLevel type where applicable.
>>
>> The change tested with jtreg tier1-3, :hotspot_compiler :hotspot_gc :hotspot_serviceability :hotspot_runtime
>>
>> Renaissance benchmarks shows no performance regressions on x86 and aarch.
>>
>> BEFORE:
>>
>> (gdb) ptype /o CodeBlob
>> /* offset | size */ type = class CodeBlob {
>> /* 8 | 4 */ const CompilerType _type; <<<<
>> /* 12 | 4 */ int _size;
>> /* 16 | 4 */ int _header_size;
>> /* 20 | 4 */ int _frame_complete_offset;
>> /* 24 | 4 */ int _data_offset;
>> /* 28 | 4 */ int _frame_size;
>> /* 32 | 8 */ address _code_begin;
>> /* 40 | 8 */ address _code_end;
>> /* 48 | 8 */ address _content_begin;
>> /* 56 | 8 */ address _data_end;
>> /* 64 | 8 */ address _relocation_begin;
>> /* 72 | 8 */ address _relocation_end;
>> /* 80 | 8 */ ImmutableOopMapSet *_oop_maps;
>> /* 88 | 1 */ bool _caller_must_gc_arguments;
>> /* 89 | 1 */ bool _is_compiled;
>> /* XXX 6-byte hole */
>> /* 96 | 8 */ const char *_name;
>> /* 104 | 8 */ class AsmRemarks {
>> /* 104 | 8 */ AsmRemarkCollection *_remarks;
>> } _asm_remarks;
>> /* 112 | 8 */ class DbgStrings {
>> /* 112 | 8 */ DbgStringCollection *_strings;
>> } _dbg_strings;
>>
>> /* total size (bytes): 120 */
>> }
>>
>> AFTER:
>>
>> (gdb) ptype /o CodeBlob
>> /* offset | size */ type = class CodeBlob {
>> protected:
>> /* 8 | 8 */ address _code_begin;
>> /* 16 | 8 */ address _code_end;
>> /* 24 | 8 */ address _content_begin;
>> /* 32 | 8 */ address _data_end;
>> /* 40 | 8 */ address _relocation_begin;
>> /* 48 | 8 */ address _relocation_end;
>> /* 56 | 8 */ ImmutableOopMapSet *_oop_maps;
>> /* 64 | 8 */ const char *_name;
>> /* 72 | 4 */ int _size;
>> /* 76 | 4 */ int _header_size;
>> /* 80 | 4 */ int _frame_complete_offset;
>> /* 84 | 4 */ int _data_offset;
>> /* 88 | 4 */ int _frame_size;
>> /* 92 | 1 */ bool _caller_must_gc_arguments;
>> /* 93 | 1 */ bool _is_compiled;
>> /* 94 | 1 */ const CompilerType _type; <<<<
>> /* XXX 1-byte hole */
>> /* 96 | 8 */ class AsmRemarks {
>> /* 96 | 8 */ AsmRemarkCollection *_remarks;
>> } _asm_remarks;
>> /* 104 | 8 */ class DbgStrings {
>> /* 104 | 8 */ DbgStringCollection *_strings;
>> } _dbg_strings;
>>
>> /* total size (bytes): 112 */
>> }
>>
>> BEFORE:
>>
>> (gdb) ptype /o nmethod
>> /* offset | size */ type = class nmethod : public CompiledMethod {
>> private:
>> /* 208 | 4 */ int _entry_bci;
>> /* XXX 4-byte hole */
>> /* 216 | 8 */ uint64_t _gc_epoch;
>> /* 224 | 8 */ nmethod *_osr_link;
>> /* 232 | 8 */ nmethod::oops_do_mark_link * volatile _oops_do_mark_link;
>> /* 240 | 8 */ address _entry_point;
>> /* 248 | 8 */ address _verified_entry_point;
>> /* 256 | 8 */ address _osr_entry_point;
>> /* 264 | 4 */ int _exception_offset;
>> /* 268 | 4 */ int _unwind_handler_offset;
>> /* 272 | 4 */ int _consts_offset;
>> /* 276 | 4 */ int _stub_offset;
>> /* 280 | 4 */ int _oops_offset;
>> /* 284 | 4 */ int _metadata_offset;
>> /* 288 | 4 */ int _scopes_data_offset;
>> /* 292 | 4 */ int _scopes_pcs_offset;
>> /* 296 | 4 */ int _dependencies_offset;
>> /* 300 | 4 */ int _handler_table_offset;
>> /* 304 | 4 */ int _nul_chk_table_offset;
>> /* 308 | 4 */ int _speculations_offset;
>> /* 312 | 4 */ int _jvmci_data_offset;
>> /* 316 | 4 */ int _nmethod_end_offset;
>> /* 320 | 4 */ int _orig_pc_offset;
>> /* 324 | 4 */ int _compile_id;
>> /* 328 | 4 */ int _comp_level; <<<<
>> /* 332 | 1 */ bool _has_flushed_dependencies;
>> /* 333 | 1 */ bool _unload_reported;
>> /* 334 | 1 */ bool _load_reported;
>> /* 335 | 1 */ volatile signed char _state;
>> /* 336 | 1 */ bool _oops_are_stale;
>> /* XXX 3-byte hole */
>> /* 340 | 4 */ RTMState _rtm_state;
>> /* 344 | 4 */ volatile jint _lock_count;
>> /* XXX 4-byte hole */
>> /* 352 | 8 */ volatile int64_t _stack_traversal_mark;
>> /* 360 | 4 */ int _hotness_counter;
>> /* 364 | 1 */ volatile uint8_t _is_unloading_state;
>> /* XXX 3-byte hole */
>> /* 368 | 4 */ ByteSize _native_receiver_sp_offset;
>> /* 372 | 4 */ ByteSize _native_basic_lock_sp_offset;
>>
>> /* total size (bytes): 376 */
>> }
>>
>> AFTER:
>>
>> (gdb) ptype /o nmethod
>> /* offset | size */ type = class nmethod : public CompiledMethod {
>> /* 200 | 8 */ uint64_t _gc_epoch;
>> /* 208 | 8 */ volatile int64_t _stack_traversal_mark;
>> /* 216 | 8 */ nmethod *_osr_link;
>> /* 224 | 8 */ nmethod::oops_do_mark_link * volatile _oops_do_mark_link;
>> /* 232 | 8 */ address _entry_point;
>> /* 240 | 8 */ address _verified_entry_point;
>> /* 248 | 8 */ address _osr_entry_point;
>> /* 256 | 4 */ int _entry_bci;
>> /* 260 | 4 */ int _exception_offset;
>> /* 264 | 4 */ int _unwind_handler_offset;
>> /* 268 | 4 */ int _consts_offset;
>> /* 272 | 4 */ int _stub_offset;
>> /* 276 | 4 */ int _oops_offset;
>> /* 280 | 4 */ int _metadata_offset;
>> /* 284 | 4 */ int _scopes_data_offset;
>> /* 288 | 4 */ int _scopes_pcs_offset;
>> /* 292 | 4 */ int _dependencies_offset;
>> /* 296 | 4 */ int _handler_table_offset;
>> /* 300 | 4 */ int _nul_chk_table_offset;
>> /* 304 | 4 */ int _speculations_offset;
>> /* 308 | 4 */ int _jvmci_data_offset;
>> /* 312 | 4 */ int _nmethod_end_offset;
>> /* 316 | 4 */ int _orig_pc_offset;
>> /* 320 | 4 */ int _compile_id;
>> /* 324 | 4 */ RTMState _rtm_state;
>> /* 328 | 4 */ volatile jint _lock_count;
>> /* 332 | 4 */ int _hotness_counter;
>> /* 336 | 4 */ ByteSize _native_receiver_sp_offset;
>> /* 340 | 4 */ ByteSize _native_basic_lock_sp_offset;
>> /* 344 | 1 */ CompLevel _comp_level; <<<<
>> /* 345 | 1 */ volatile uint8_t _is_unloading_state;
>> /* 346 | 1 */ bool _has_flushed_dependencies;
>> /* 347 | 1 */ bool _unload_reported;
>> /* 348 | 1 */ bool _load_reported;
>> /* 349 | 1 */ volatile signed char _state;
>> /* 350 | 1 */ bool _oops_are_stale;
>>
>> /* total size (bytes): 352 */
>> }
>
> Boris Ulasevich has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains one new commit since the last revision:
>
> Undo applying CompLevel where applicable. It must be a separate change
Doug is out but I took a look. The changes look fine and since Graal doesn't access nmethod::_comp_level directly we don't need to adjust to these changes.
src/hotspot/share/jvmci/vmStructs_jvmci.cpp line 258:
> 256: \
> 257: nonstatic_field(nmethod, _verified_entry_point, address) \
> 258: nonstatic_field(nmethod, _comp_level, int) \
You should declare CompLevel in this file as well. I think it might be missing the sanity checking that detect missing type declarations.
-------------
Marked as reviewed by never (Reviewer).
PR: https://git.openjdk.org/jdk/pull/9165
More information about the hotspot-dev
mailing list