diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 7e4f6994ff1c6..26d393d06db45 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -110,6 +110,11 @@ #endif +// Cast from int value to narrow type +#define CHECKED_CAST(result, T, thing) \ + result = static_cast(thing); \ + assert(static_cast(result) == thing, "failed: %d != %d", static_cast(result), thing); + //--------------------------------------------------------------------------------- // NMethod statistics // They are printed under various flags, including: @@ -121,26 +126,28 @@ // and make it simpler to print from the debugger. struct java_nmethod_stats_struct { uint nmethod_count; - uint total_size; + uint total_nm_size; + uint total_immut_size; uint relocation_size; uint consts_size; uint insts_size; uint stub_size; - uint scopes_data_size; - uint scopes_pcs_size; + uint oops_size; + uint metadata_size; uint dependencies_size; - uint handler_table_size; uint nul_chk_table_size; + uint handler_table_size; + uint scopes_pcs_size; + uint scopes_data_size; #if INCLUDE_JVMCI uint speculations_size; uint jvmci_data_size; #endif - uint oops_size; - uint metadata_size; void note_nmethod(nmethod* nm) { nmethod_count += 1; - total_size += nm->size(); + total_nm_size += nm->size(); + total_immut_size += nm->immutable_data_size(); relocation_size += nm->relocation_size(); consts_size += nm->consts_size(); insts_size += nm->insts_size(); @@ -160,23 +167,60 @@ struct java_nmethod_stats_struct { void print_nmethod_stats(const char* name) { if (nmethod_count == 0) return; tty->print_cr("Statistics for %u bytecoded nmethods for %s:", nmethod_count, name); - if (total_size != 0) tty->print_cr(" total in heap = %u (100%%)", total_size); + uint total_size = total_nm_size + total_immut_size; + if (total_nm_size != 0) { + tty->print_cr(" total size = %u (100%%)", total_size); + tty->print_cr(" in CodeCache = %u (%f%%)", total_nm_size, (total_nm_size * 100.0f)/total_size); + } uint header_size = (uint)(nmethod_count * sizeof(nmethod)); - if (nmethod_count != 0) tty->print_cr(" header = %u (%f%%)", header_size, (header_size * 100.0f)/total_size); - if (relocation_size != 0) tty->print_cr(" relocation = %u (%f%%)", relocation_size, (relocation_size * 100.0f)/total_size); - if (consts_size != 0) tty->print_cr(" constants = %u (%f%%)", consts_size, (consts_size * 100.0f)/total_size); - if (insts_size != 0) tty->print_cr(" main code = %u (%f%%)", insts_size, (insts_size * 100.0f)/total_size); - if (stub_size != 0) tty->print_cr(" stub code = %u (%f%%)", stub_size, (stub_size * 100.0f)/total_size); - if (oops_size != 0) tty->print_cr(" oops = %u (%f%%)", oops_size, (oops_size * 100.0f)/total_size); - if (metadata_size != 0) tty->print_cr(" metadata = %u (%f%%)", metadata_size, (metadata_size * 100.0f)/total_size); - if (scopes_data_size != 0) tty->print_cr(" scopes data = %u (%f%%)", scopes_data_size, (scopes_data_size * 100.0f)/total_size); - if (scopes_pcs_size != 0) tty->print_cr(" scopes pcs = %u (%f%%)", scopes_pcs_size, (scopes_pcs_size * 100.0f)/total_size); - if (dependencies_size != 0) tty->print_cr(" dependencies = %u (%f%%)", dependencies_size, (dependencies_size * 100.0f)/total_size); - if (handler_table_size != 0) tty->print_cr(" handler table = %u (%f%%)", handler_table_size, (handler_table_size * 100.0f)/total_size); - if (nul_chk_table_size != 0) tty->print_cr(" nul chk table = %u (%f%%)", nul_chk_table_size, (nul_chk_table_size * 100.0f)/total_size); + if (nmethod_count != 0) { + tty->print_cr(" header = %u (%f%%)", header_size, (header_size * 100.0f)/total_nm_size); + } + if (relocation_size != 0) { + tty->print_cr(" relocation = %u (%f%%)", relocation_size, (relocation_size * 100.0f)/total_nm_size); + } + if (consts_size != 0) { + tty->print_cr(" constants = %u (%f%%)", consts_size, (consts_size * 100.0f)/total_nm_size); + } + if (insts_size != 0) { + tty->print_cr(" main code = %u (%f%%)", insts_size, (insts_size * 100.0f)/total_nm_size); + } + if (stub_size != 0) { + tty->print_cr(" stub code = %u (%f%%)", stub_size, (stub_size * 100.0f)/total_nm_size); + } + if (oops_size != 0) { + tty->print_cr(" oops = %u (%f%%)", oops_size, (oops_size * 100.0f)/total_nm_size); + } + if (metadata_size != 0) { + tty->print_cr(" metadata = %u (%f%%)", metadata_size, (metadata_size * 100.0f)/total_nm_size); + } #if INCLUDE_JVMCI - if (speculations_size != 0) tty->print_cr(" speculations = %u (%f%%)", speculations_size, (speculations_size * 100.0f)/total_size); - if (jvmci_data_size != 0) tty->print_cr(" JVMCI data = %u (%f%%)", jvmci_data_size, (jvmci_data_size * 100.0f)/total_size); + if (jvmci_data_size != 0) { + tty->print_cr(" JVMCI data = %u (%f%%)", jvmci_data_size, (jvmci_data_size * 100.0f)/total_nm_size); + } +#endif + if (total_immut_size != 0) { + tty->print_cr(" immutable data = %u (%f%%)", total_immut_size, (total_immut_size * 100.0f)/total_size); + } + if (dependencies_size != 0) { + tty->print_cr(" dependencies = %u (%f%%)", dependencies_size, (dependencies_size * 100.0f)/total_immut_size); + } + if (nul_chk_table_size != 0) { + tty->print_cr(" nul chk table = %u (%f%%)", nul_chk_table_size, (nul_chk_table_size * 100.0f)/total_immut_size); + } + if (handler_table_size != 0) { + tty->print_cr(" handler table = %u (%f%%)", handler_table_size, (handler_table_size * 100.0f)/total_immut_size); + } + if (scopes_pcs_size != 0) { + tty->print_cr(" scopes pcs = %u (%f%%)", scopes_pcs_size, (scopes_pcs_size * 100.0f)/total_immut_size); + } + if (scopes_data_size != 0) { + tty->print_cr(" scopes data = %u (%f%%)", scopes_data_size, (scopes_data_size * 100.0f)/total_immut_size); + } +#if INCLUDE_JVMCI + if (speculations_size != 0) { + tty->print_cr(" speculations = %u (%f%%)", speculations_size, (speculations_size * 100.0f)/total_immut_size); + } #endif } }; @@ -1101,31 +1145,40 @@ nmethod* nmethod::new_nmethod(const methodHandle& method, code_buffer->finalize_oop_references(method); // create nmethod nmethod* nm = nullptr; + int nmethod_size = CodeBlob::allocation_size(code_buffer, sizeof(nmethod)); #if INCLUDE_JVMCI - int jvmci_data_size = compiler->is_jvmci() ? jvmci_data->size() : 0; + if (compiler->is_jvmci()) { + nmethod_size += align_up(jvmci_data->size(), oopSize); + } #endif - int nmethod_size = - CodeBlob::allocation_size(code_buffer, sizeof(nmethod)) - + adjust_pcs_size(debug_info->pcs_size()) + + int immutable_data_size = + adjust_pcs_size(debug_info->pcs_size()) + align_up((int)dependencies->size_in_bytes(), oopSize) + align_up(handler_table->size_in_bytes() , oopSize) + align_up(nul_chk_table->size_in_bytes() , oopSize) #if INCLUDE_JVMCI + align_up(speculations_len , oopSize) - + align_up(jvmci_data_size , oopSize) #endif + align_up(debug_info->data_size() , oopSize); + + // First, allocate space for immutable data in C heap. + address immutable_data = nullptr; + if (immutable_data_size > 0) { + immutable_data = (address)os::malloc(immutable_data_size, mtCode); + if (immutable_data == nullptr) { + vm_exit_out_of_memory(immutable_data_size, OOM_MALLOC_ERROR, "nmethod: no space for immutable data"); + return nullptr; + } + } { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); nm = new (nmethod_size, comp_level) - nmethod(method(), compiler->type(), nmethod_size, compile_id, entry_bci, offsets, - orig_pc_offset, debug_info, dependencies, code_buffer, frame_size, - oop_maps, - handler_table, - nul_chk_table, - compiler, - comp_level + nmethod(method(), compiler->type(), nmethod_size, immutable_data_size, + compile_id, entry_bci, immutable_data, offsets, orig_pc_offset, + debug_info, dependencies, code_buffer, frame_size, oop_maps, + handler_table, nul_chk_table, compiler, comp_level #if INCLUDE_JVMCI , speculations, speculations_len, @@ -1196,11 +1249,11 @@ void nmethod::init_defaults(CodeBuffer *code_buffer, CodeOffsets* offsets) { int consts_offset = code_buffer->total_offset_of(code_buffer->consts()); assert(consts_offset == 0, "const_offset: %d", consts_offset); - _entry_offset = checked_cast(offsets->value(CodeOffsets::Entry)); - _verified_entry_offset = checked_cast(offsets->value(CodeOffsets::Verified_Entry)); - _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); + _stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs()); - _skipped_instructions_size = checked_cast(code_buffer->total_skipped_instructions_size()); + CHECKED_CAST(_entry_offset, uint16_t, (offsets->value(CodeOffsets::Entry))); + CHECKED_CAST(_verified_entry_offset, uint16_t, (offsets->value(CodeOffsets::Verified_Entry))); + CHECKED_CAST(_skipped_instructions_size, uint16_t, (code_buffer->total_skipped_instructions_size())); } // Post initialization @@ -1262,21 +1315,26 @@ nmethod::nmethod( _deopt_mh_handler_offset = 0; _unwind_handler_offset = 0; - _metadata_offset = checked_cast(align_up(code_buffer->total_oop_size(), oopSize)); - _dependencies_offset = checked_cast(_metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize)); - _scopes_pcs_offset = _dependencies_offset; - _scopes_data_offset = _scopes_pcs_offset; - _handler_table_offset = _scopes_data_offset; - _nul_chk_table_offset = _handler_table_offset; + CHECKED_CAST(_metadata_offset, uint16_t, (align_up(code_buffer->total_oop_size(), oopSize))); + int data_end_offset = _metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize); #if INCLUDE_JVMCI - _speculations_offset = _nul_chk_table_offset; - _jvmci_data_offset = _speculations_offset; - DEBUG_ONLY( int data_end_offset = _jvmci_data_offset; ) -#else - DEBUG_ONLY( int data_end_offset = _nul_chk_table_offset; ) + // jvmci_data_size is 0 in native wrapper but we need to set offset + // to correctly calculate metadata_end address + CHECKED_CAST(_jvmci_data_offset, uint16_t, data_end_offset); #endif assert((data_offset() + data_end_offset) <= nmethod_size, "wrong nmethod's size: %d < %d", nmethod_size, (data_offset() + data_end_offset)); + // native wrapper does not have read-only data but we need unique not null address + _immutable_data = data_end(); + _immutable_data_size = 0; + _nul_chk_table_offset = 0; + _handler_table_offset = 0; + _scopes_pcs_offset = 0; + _scopes_data_offset = 0; +#if INCLUDE_JVMCI + _speculations_offset = 0; +#endif + code_buffer->copy_code_and_locs_to(this); code_buffer->copy_values_to(this); @@ -1343,8 +1401,10 @@ nmethod::nmethod( Method* method, CompilerType type, int nmethod_size, + int immutable_data_size, int compile_id, int entry_bci, + address immutable_data, CodeOffsets* offsets, int orig_pc_offset, DebugInformationRecorder* debug_info, @@ -1421,25 +1481,48 @@ nmethod::nmethod( } } if (offsets->value(CodeOffsets::UnwindHandler) != -1) { - _unwind_handler_offset = code_offset() + offsets->value(CodeOffsets::UnwindHandler); + // C1 generates UnwindHandler at the end of instructions section. + // Calculate positive offset as distance between the start of stubs section + // (which is also the end of instructions section) and the start of the handler. + int unwind_handler_offset = code_offset() + offsets->value(CodeOffsets::UnwindHandler); + CHECKED_CAST(_unwind_handler_offset, int16_t, (_stub_offset - unwind_handler_offset)); } else { _unwind_handler_offset = -1; } - _metadata_offset = checked_cast(align_up(code_buffer->total_oop_size(), oopSize)); - _dependencies_offset = checked_cast(_metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize)); - _scopes_pcs_offset = checked_cast(_dependencies_offset + align_up((int)dependencies->size_in_bytes(), oopSize)); - _scopes_data_offset = _scopes_pcs_offset + adjust_pcs_size(debug_info->pcs_size()); - _handler_table_offset = _scopes_data_offset + align_up(debug_info->data_size (), oopSize); - _nul_chk_table_offset = _handler_table_offset + align_up(handler_table->size_in_bytes(), oopSize); + CHECKED_CAST(_metadata_offset, uint16_t, (align_up(code_buffer->total_oop_size(), oopSize))); + int metadata_end_offset = _metadata_offset + align_up(code_buffer->total_metadata_size(), wordSize); + #if INCLUDE_JVMCI - _speculations_offset = _nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize); - _jvmci_data_offset = _speculations_offset + align_up(speculations_len, oopSize); + CHECKED_CAST(_jvmci_data_offset, uint16_t, metadata_end_offset); int jvmci_data_size = compiler->is_jvmci() ? jvmci_data->size() : 0; - DEBUG_ONLY( int data_end_offset = _jvmci_data_offset + align_up(jvmci_data_size, oopSize); ) + DEBUG_ONLY( int data_end_offset = _jvmci_data_offset + align_up(jvmci_data_size, oopSize); ) #else - DEBUG_ONLY( int data_end_offset = _nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize); ) + DEBUG_ONLY( int data_end_offset = metadata_end_offset; ) #endif - assert((data_offset() + data_end_offset) <= nmethod_size, "wrong nmethod's size: %d < %d", nmethod_size, (data_offset() + data_end_offset)); + assert((data_offset() + data_end_offset) <= nmethod_size, "wrong nmethod's size: %d > %d", + (data_offset() + data_end_offset), nmethod_size); + + _immutable_data_size = immutable_data_size; + if (immutable_data_size > 0) { + assert(immutable_data != nullptr, "required"); + _immutable_data = immutable_data; + } else { + // We need unique not null address + _immutable_data = data_end(); + } + CHECKED_CAST(_nul_chk_table_offset, uint16_t, (align_up((int)dependencies->size_in_bytes(), oopSize))); + CHECKED_CAST(_handler_table_offset, uint16_t, (_nul_chk_table_offset + align_up(nul_chk_table->size_in_bytes(), oopSize))); + _scopes_pcs_offset = _handler_table_offset + align_up(handler_table->size_in_bytes(), oopSize); + _scopes_data_offset = _scopes_pcs_offset + adjust_pcs_size(debug_info->pcs_size()); + +#if INCLUDE_JVMCI + _speculations_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); + DEBUG_ONLY( int immutable_data_end_offset = _speculations_offset + align_up(speculations_len, oopSize); ) +#else + DEBUG_ONLY( int immutable_data_end_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); ) +#endif + assert(immutable_data_end_offset <= immutable_data_size, "wrong read-only data size: %d > %d", + immutable_data_end_offset, immutable_data_size); // Copy code and relocation info code_buffer->copy_code_and_locs_to(this); @@ -2047,6 +2130,10 @@ void nmethod::purge(bool unregister_nmethod) { } delete[] _compiled_ic_data; + if (_immutable_data != data_end()) { + os::free(_immutable_data); + _immutable_data = data_end(); // Valid not null address + } if (unregister_nmethod) { Universe::heap()->unregister_nmethod(this); } @@ -2679,7 +2766,7 @@ PcDesc* PcDescContainer::find_pc_desc_internal(address pc, bool approximate, add // Find the last pc_offset less than the given offset. // The successor must be the required match, if there is a match at all. // (Use a fixed radix to avoid expensive affine pointer arithmetic.) - PcDesc* lower = lower_incl; // this is initial sentiel + PcDesc* lower = lower_incl; // this is initial sentinel PcDesc* upper = upper_incl - 1; // exclude final sentinel if (lower >= upper) return nullptr; // no PcDescs at all @@ -3002,35 +3089,41 @@ void nmethod::print(outputStream* st) const { p2i(metadata_begin()), p2i(metadata_end()), metadata_size()); - if (scopes_data_size () > 0) st->print_cr(" scopes data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", - p2i(scopes_data_begin()), - p2i(scopes_data_end()), - scopes_data_size()); - if (scopes_pcs_size () > 0) st->print_cr(" scopes pcs [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", - p2i(scopes_pcs_begin()), - p2i(scopes_pcs_end()), - scopes_pcs_size()); +#if INCLUDE_JVMCI + if (jvmci_data_size () > 0) st->print_cr(" JVMCI data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(jvmci_data_begin()), + p2i(jvmci_data_end()), + jvmci_data_size()); +#endif + if (immutable_data_size() > 0) st->print_cr(" immutable data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(immutable_data_begin()), + p2i(immutable_data_end()), + immutable_data_size()); if (dependencies_size () > 0) st->print_cr(" dependencies [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(dependencies_begin()), p2i(dependencies_end()), dependencies_size()); - if (handler_table_size() > 0) st->print_cr(" handler table [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", - p2i(handler_table_begin()), - p2i(handler_table_end()), - handler_table_size()); if (nul_chk_table_size() > 0) st->print_cr(" nul chk table [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(nul_chk_table_begin()), p2i(nul_chk_table_end()), nul_chk_table_size()); + if (handler_table_size() > 0) st->print_cr(" handler table [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(handler_table_begin()), + p2i(handler_table_end()), + handler_table_size()); + if (scopes_pcs_size () > 0) st->print_cr(" scopes pcs [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(scopes_pcs_begin()), + p2i(scopes_pcs_end()), + scopes_pcs_size()); + if (scopes_data_size () > 0) st->print_cr(" scopes data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", + p2i(scopes_data_begin()), + p2i(scopes_data_end()), + scopes_data_size()); #if INCLUDE_JVMCI if (speculations_size () > 0) st->print_cr(" speculations [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(speculations_begin()), p2i(speculations_end()), speculations_size()); - if (jvmci_data_size () > 0) st->print_cr(" JVMCI data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", - p2i(jvmci_data_begin()), - p2i(jvmci_data_end()), - jvmci_data_size()); #endif } diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 8ffb75eda34d4..22e38afeebd67 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -195,6 +195,9 @@ class nmethod : public CodeBlob { }; }; + // nmethod's read-only data + address _immutable_data; + PcDescContainer* _pc_desc_container; ExceptionCache* volatile _exception_cache; @@ -211,6 +214,7 @@ class nmethod : public CodeBlob { uint16_t _entry_offset; // entry point with class check uint16_t _verified_entry_offset; // entry point without class check int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method + int _immutable_data_size; // _consts_offset == _content_offset because SECT_CONSTS is first in code buffer @@ -224,21 +228,27 @@ class nmethod : public CodeBlob { // All deoptee's at a MethodHandle call site will resume execution // at this location described by this offset. int _deopt_mh_handler_offset; - // Offset of the unwind handler if it exists - int _unwind_handler_offset; - + // Offset (from insts_end) of the unwind handler if it exists + int16_t _unwind_handler_offset; + // Number of arguments passed on the stack + uint16_t _num_stack_arg_slots; uint16_t _skipped_instructions_size; + // Offsets in mutable data section // _oops_offset == _data_offset, offset where embedded oop table begins (inside data) uint16_t _metadata_offset; // embedded meta data table - uint16_t _dependencies_offset; - uint16_t _scopes_pcs_offset; +#if INCLUDE_JVMCI + uint16_t _jvmci_data_offset; +#endif + + // Offset in immutable data section + // _dependencies_offset == 0 + uint16_t _nul_chk_table_offset; + uint16_t _handler_table_offset; // This table could be big in C1 code + int _scopes_pcs_offset; int _scopes_data_offset; - int _handler_table_offset; - int _nul_chk_table_offset; #if INCLUDE_JVMCI int _speculations_offset; - int _jvmci_data_offset; #endif // location in frame (offset for sp) that deopt can store the original @@ -249,8 +259,6 @@ class nmethod : public CodeBlob { CompLevel _comp_level; // compilation level (s1) CompilerType _compiler_type; // which compiler made this nmethod (u1) - uint16_t _num_stack_arg_slots; // Number of arguments passed on the stack - #if INCLUDE_RTM_OPT // RTM state at compile time. Used during deoptimization to decide // whether to restart collecting RTM locking abort statistic again. @@ -307,8 +315,10 @@ class nmethod : public CodeBlob { nmethod(Method* method, CompilerType type, int nmethod_size, + int immutable_data_size, int compile_id, int entry_bci, + address immutable_data, CodeOffsets* offsets, int orig_pc_offset, DebugInformationRecorder *recorder, @@ -524,48 +534,56 @@ class nmethod : public CodeBlob { address exception_begin () const { return header_begin() + _exception_offset ; } address deopt_handler_begin () const { return header_begin() + _deopt_handler_offset ; } address deopt_mh_handler_begin() const { return header_begin() + _deopt_mh_handler_offset ; } - address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (header_begin() + _unwind_handler_offset) : nullptr; } - - oop* oops_begin () const { return (oop*) data_begin(); } - oop* oops_end () const { return (oop*) (data_begin() + _metadata_offset) ; } + address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (insts_end() - _unwind_handler_offset) : nullptr; } + // mutable data + oop* oops_begin () const { return (oop*) data_begin(); } + oop* oops_end () const { return (oop*) (data_begin() + _metadata_offset) ; } Metadata** metadata_begin () const { return (Metadata**) (data_begin() + _metadata_offset) ; } - Metadata** metadata_end () const { return (Metadata**) (data_begin() + _dependencies_offset) ; } - - address dependencies_begin () const { return data_begin() + _dependencies_offset ; } - address dependencies_end () const { return data_begin() + _scopes_pcs_offset ; } - PcDesc* scopes_pcs_begin () const { return (PcDesc*)(data_begin() + _scopes_pcs_offset) ; } - PcDesc* scopes_pcs_end () const { return (PcDesc*)(data_begin() + _scopes_data_offset) ; } - address scopes_data_begin () const { return data_begin() + _scopes_data_offset ; } - address scopes_data_end () const { return data_begin() + _handler_table_offset ; } - address handler_table_begin () const { return data_begin() + _handler_table_offset ; } - address handler_table_end () const { return data_begin() + _nul_chk_table_offset ; } - address nul_chk_table_begin () const { return data_begin() + _nul_chk_table_offset ; } +#if INCLUDE_JVMCI + Metadata** metadata_end () const { return (Metadata**) (data_begin() + _jvmci_data_offset) ; } + address jvmci_data_begin () const { return data_begin() + _jvmci_data_offset ; } + address jvmci_data_end () const { return data_end(); } +#else + Metadata** metadata_end () const { return (Metadata**) data_end(); } +#endif + + // immutable data + address immutable_data_begin () const { return _immutable_data; } + address immutable_data_end () const { return _immutable_data + _immutable_data_size ; } + address dependencies_begin () const { return _immutable_data; } + address dependencies_end () const { return _immutable_data + _nul_chk_table_offset; } + address nul_chk_table_begin () const { return _immutable_data + _nul_chk_table_offset; } + address nul_chk_table_end () const { return _immutable_data + _handler_table_offset; } + address handler_table_begin () const { return _immutable_data + _handler_table_offset; } + address handler_table_end () const { return _immutable_data + _scopes_pcs_offset ; } + PcDesc* scopes_pcs_begin () const { return (PcDesc*)(_immutable_data + _scopes_pcs_offset) ; } + PcDesc* scopes_pcs_end () const { return (PcDesc*)(_immutable_data + _scopes_data_offset) ; } + address scopes_data_begin () const { return _immutable_data + _scopes_data_offset ; } #if INCLUDE_JVMCI - address nul_chk_table_end () const { return data_begin() + _speculations_offset ; } - address speculations_begin () const { return data_begin() + _speculations_offset ; } - address speculations_end () const { return data_begin() + _jvmci_data_offset ; } - address jvmci_data_begin () const { return data_begin() + _jvmci_data_offset ; } - address jvmci_data_end () const { return data_end(); } + address scopes_data_end () const { return _immutable_data + _speculations_offset ; } + address speculations_begin () const { return _immutable_data + _speculations_offset ; } + address speculations_end () const { return immutable_data_end(); } #else - address nul_chk_table_end () const { return data_end(); } + address scopes_data_end () const { return immutable_data_end(); } #endif // Sizes - int consts_size () const { return int( consts_end () - consts_begin ()); } - int insts_size () const { return int( insts_end () - insts_begin ()); } - int stub_size () const { return int( stub_end () - stub_begin ()); } - int oops_size () const { return int((address) oops_end () - (address) oops_begin ()); } - int metadata_size () const { return int((address) metadata_end () - (address) metadata_begin ()); } - int scopes_data_size () const { return int( scopes_data_end () - scopes_data_begin ()); } - int scopes_pcs_size () const { return int((intptr_t)scopes_pcs_end () - (intptr_t)scopes_pcs_begin ()); } - int dependencies_size () const { return int( dependencies_end () - dependencies_begin ()); } - int handler_table_size() const { return int( handler_table_end() - handler_table_begin()); } - int nul_chk_table_size() const { return int( nul_chk_table_end() - nul_chk_table_begin()); } + int immutable_data_size() const { return _immutable_data_size; } + int consts_size () const { return int( consts_end () - consts_begin ()); } + int insts_size () const { return int( insts_end () - insts_begin ()); } + int stub_size () const { return int( stub_end () - stub_begin ()); } + int oops_size () const { return int((address) oops_end () - (address) oops_begin ()); } + int metadata_size () const { return int((address) metadata_end () - (address) metadata_begin ()); } + int scopes_data_size () const { return int( scopes_data_end () - scopes_data_begin ()); } + int scopes_pcs_size () const { return int((intptr_t)scopes_pcs_end () - (intptr_t)scopes_pcs_begin ()); } + int dependencies_size () const { return int( dependencies_end () - dependencies_begin ()); } + int handler_table_size () const { return int( handler_table_end() - handler_table_begin()); } + int nul_chk_table_size () const { return int( nul_chk_table_end() - nul_chk_table_begin()); } #if INCLUDE_JVMCI - int speculations_size () const { return int( speculations_end () - speculations_begin ()); } - int jvmci_data_size () const { return int( jvmci_data_end () - jvmci_data_begin ()); } + int speculations_size () const { return int( speculations_end () - speculations_begin ()); } + int jvmci_data_size () const { return int( jvmci_data_end () - jvmci_data_begin ()); } #endif int oops_count() const { assert(oops_size() % oopSize == 0, ""); return (oops_size() / oopSize) + 1; } diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 8d86fb6ceb4bf..cc1351e2742ee 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -576,14 +576,15 @@ nonstatic_field(nmethod, _orig_pc_offset, int) \ nonstatic_field(nmethod, _stub_offset, int) \ nonstatic_field(nmethod, _metadata_offset, u2) \ - nonstatic_field(nmethod, _scopes_pcs_offset, u2) \ + nonstatic_field(nmethod, _scopes_pcs_offset, int) \ nonstatic_field(nmethod, _scopes_data_offset, int) \ - nonstatic_field(nmethod, _dependencies_offset, u2) \ - nonstatic_field(nmethod, _handler_table_offset, int) \ - nonstatic_field(nmethod, _nul_chk_table_offset, int) \ + nonstatic_field(nmethod, _handler_table_offset, u2) \ + nonstatic_field(nmethod, _nul_chk_table_offset, u2) \ nonstatic_field(nmethod, _entry_offset, u2) \ nonstatic_field(nmethod, _verified_entry_offset, u2) \ nonstatic_field(nmethod, _osr_entry_point, address) \ + nonstatic_field(nmethod, _immutable_data, address) \ + nonstatic_field(nmethod, _immutable_data_size, int) \ nonstatic_field(nmethod, _compile_id, int) \ nonstatic_field(nmethod, _comp_level, CompLevel) \ volatile_nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java index edcf85ce0c78f..ec329aa131a9b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -42,6 +42,8 @@ public class NMethod extends CodeBlob { private static CIntegerField entryBCIField; /** To support simple linked-list chaining of nmethods */ private static AddressField osrLinkField; + private static AddressField immutableDataField; + private static CIntegerField immutableDataSizeField; /** Offsets for different nmethod parts */ private static CIntegerField exceptionOffsetField; @@ -50,11 +52,10 @@ public class NMethod extends CodeBlob { private static CIntegerField origPCOffsetField; private static CIntegerField stubOffsetField; private static CIntField metadataOffsetField; - private static CIntField dependenciesOffsetField; - private static CIntField scopesPCsOffsetField; + private static CIntField handlerTableOffsetField; + private static CIntField nulChkTableOffsetField; + private static CIntegerField scopesPCsOffsetField; private static CIntegerField scopesDataOffsetField; - private static CIntegerField handlerTableOffsetField; - private static CIntegerField nulChkTableOffsetField; /** Offsets for entry points */ /** Entry point with class check */ @@ -82,6 +83,8 @@ private static void initialize(TypeDataBase db) { methodField = type.getAddressField("_method"); entryBCIField = type.getCIntegerField("_entry_bci"); osrLinkField = type.getAddressField("_osr_link"); + immutableDataField = type.getAddressField("_immutable_data"); + immutableDataSizeField = type.getCIntegerField("_immutable_data_size"); exceptionOffsetField = type.getCIntegerField("_exception_offset"); deoptHandlerOffsetField = type.getCIntegerField("_deopt_handler_offset"); @@ -89,11 +92,10 @@ private static void initialize(TypeDataBase db) { origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); stubOffsetField = type.getCIntegerField("_stub_offset"); metadataOffsetField = new CIntField(type.getCIntegerField("_metadata_offset"), 0); - dependenciesOffsetField = new CIntField(type.getCIntegerField("_dependencies_offset"), 0); - scopesPCsOffsetField = new CIntField(type.getCIntegerField("_scopes_pcs_offset"), 0); + scopesPCsOffsetField = type.getCIntegerField("_scopes_pcs_offset"); scopesDataOffsetField = type.getCIntegerField("_scopes_data_offset"); - handlerTableOffsetField = type.getCIntegerField("_handler_table_offset"); - nulChkTableOffsetField = type.getCIntegerField("_nul_chk_table_offset"); + handlerTableOffsetField = new CIntField(type.getCIntegerField("_handler_table_offset"), 0); + nulChkTableOffsetField = new CIntField(type.getCIntegerField("_nul_chk_table_offset"), 0); entryOffsetField = new CIntField(type.getCIntegerField("_entry_offset"), 0); verifiedEntryOffsetField = new CIntField(type.getCIntegerField("_verified_entry_offset"), 0); osrEntryPointField = type.getAddressField("_osr_entry_point"); @@ -133,18 +135,22 @@ public Method getMethod() { public Address oopsBegin() { return dataBegin(); } public Address oopsEnd() { return dataBegin().addOffsetTo(getMetadataOffset()); } public Address metadataBegin() { return dataBegin().addOffsetTo(getMetadataOffset()); } - public Address metadataEnd() { return dataBegin().addOffsetTo(getDependenciesOffset()); } - public Address dependenciesBegin() { return dataBegin().addOffsetTo(getDependenciesOffset()); } - public Address dependenciesEnd() { return dataBegin().addOffsetTo(getScopesDataOffset()); } - public Address scopesDataBegin() { return dataBegin().addOffsetTo(getScopesDataOffset()); } - public Address scopesDataEnd() { return dataBegin().addOffsetTo(getScopesPCsOffset()); } - public Address scopesPCsBegin() { return dataBegin().addOffsetTo(getScopesPCsOffset()); } - public Address scopesPCsEnd() { return dataBegin().addOffsetTo(getHandlerTableOffset()); } - public Address handlerTableBegin() { return dataBegin().addOffsetTo(getHandlerTableOffset()); } - public Address handlerTableEnd() { return dataBegin().addOffsetTo(getNulChkTableOffset()); } - public Address nulChkTableBegin() { return dataBegin().addOffsetTo(getNulChkTableOffset()); } - public Address nulChkTableEnd() { return dataEnd(); } - + public Address metadataEnd() { return dataEnd(); } + + public Address immutableDataBegin() { return immutableDataField.getValue(addr); } + public Address immutableDataEnd() { return immutableDataBegin().addOffsetTo(getImmutableDataSize()); } + public Address dependenciesBegin() { return immutableDataBegin(); } + public Address dependenciesEnd() { return immutableDataBegin().addOffsetTo(getHandlerTableOffset()); } + public Address handlerTableBegin() { return immutableDataBegin().addOffsetTo(getHandlerTableOffset()); } + public Address handlerTableEnd() { return immutableDataBegin().addOffsetTo(getNulChkTableOffset()); } + public Address nulChkTableBegin() { return immutableDataBegin().addOffsetTo(getNulChkTableOffset()); } + public Address nulChkTableEnd() { return immutableDataBegin().addOffsetTo(getScopesDataOffset()); } + public Address scopesDataBegin() { return immutableDataBegin().addOffsetTo(getScopesDataOffset()); } + public Address scopesDataEnd() { return immutableDataBegin().addOffsetTo(getScopesPCsOffset()); } + public Address scopesPCsBegin() { return immutableDataBegin().addOffsetTo(getScopesPCsOffset()); } + public Address scopesPCsEnd() { return immutableDataEnd(); } + + public int getImmutableDataSize() { return (int) immutableDataSizeField.getValue(addr); } public int constantsSize() { return (int) constantsEnd() .minus(constantsBegin()); } public int instsSize() { return (int) instsEnd() .minus(instsBegin()); } public int stubSize() { return (int) stubEnd() .minus(stubBegin()); } @@ -161,7 +167,10 @@ public int totalSize() { return constantsSize() + instsSize() + - stubSize() + + stubSize(); + } + public int immutableDataSize() { + return scopesDataSize() + scopesPCsSize() + dependenciesSize() + @@ -516,7 +525,6 @@ public void dumpReplayData(PrintStream out) { private int getMetadataOffset() { return (int) metadataOffsetField .getValue(addr); } private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); } private int getScopesPCsOffset() { return (int) scopesPCsOffsetField .getValue(addr); } - private int getDependenciesOffset() { return (int) dependenciesOffsetField.getValue(addr); } private int getHandlerTableOffset() { return (int) handlerTableOffsetField.getValue(addr); } private int getNulChkTableOffset() { return (int) nulChkTableOffsetField .getValue(addr); } private int getCompLevel() { return (int) compLevelField .getValue(addr); } diff --git a/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java b/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java index 4165fa4d0e14e..a154427530a4b 100644 --- a/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java +++ b/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8207355 * @compile TestLinearScanOrder.jasm * @run main/othervm -Xcomp -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+IgnoreUnrecognizedVMOptions -XX:NMethodSizeLimit=655360 * -XX:CompileCommand=compileonly,compiler.c1.TestLinearScanOrder::test * compiler.c1.TestLinearScanOrderMain */