< prev index next >

src/hotspot/share/code/nmethod.cpp

Print this page
rev 54763 : 8213084: Rework and enhance Print[Opto]Assembly output
Reviewed-by:

*** 22,31 **** --- 22,32 ---- * */ #include "precompiled.hpp" #include "jvm.h" + #include "asm/assembler.inline.hpp" #include "code/codeCache.hpp" #include "code/compiledIC.hpp" #include "code/compiledMethod.inline.hpp" #include "code/dependencies.hpp" #include "code/nativeInst.hpp"
*** 453,470 **** // create nmethod nmethod* nm = NULL; { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); int native_nmethod_size = CodeBlob::allocation_size(code_buffer, sizeof(nmethod)); CodeOffsets offsets; offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); ! nm = new (native_nmethod_size, CompLevel_none) nmethod(method(), compiler_none, native_nmethod_size, compile_id, &offsets, code_buffer, frame_size, basic_lock_owner_sp_offset, ! basic_lock_sp_offset, oop_maps); NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm)); } if (nm != NULL) { // verify nmethod --- 454,474 ---- // create nmethod nmethod* nm = NULL; { MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); int native_nmethod_size = CodeBlob::allocation_size(code_buffer, sizeof(nmethod)); + CodeOffsets offsets; offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); ! nm = new (native_nmethod_size, CompLevel_none) ! nmethod(method(), compiler_none, native_nmethod_size, compile_id, &offsets, code_buffer, frame_size, basic_lock_owner_sp_offset, ! basic_lock_sp_offset, ! oop_maps); NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm)); } if (nm != NULL) { // verify nmethod
*** 655,676 **** xtty->begin_head("print_native_nmethod"); xtty->method(_method); xtty->stamp(); xtty->end_head(" address='" INTPTR_FORMAT "'", (intptr_t) this); } ! // print the header part first ! print(); ! // then print the requested information if (PrintNativeNMethods) { print_code(); if (oop_maps != NULL) { ! oop_maps->print(); } } if (PrintRelocations) { print_relocations(); } if (xtty != NULL) { xtty->tail("print_native_nmethod"); } } } --- 659,694 ---- xtty->begin_head("print_native_nmethod"); xtty->method(_method); xtty->stamp(); xtty->end_head(" address='" INTPTR_FORMAT "'", (intptr_t) this); } ! // Print the header part, then print the requested information. ! // This is both handled in decode2(), called via print_code() -> decode() if (PrintNativeNMethods) { + tty->print_cr("-------------------------- Assembly (native nmethod) ---------------------------"); print_code(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); + #if defined(SUPPORT_DATA_STRUCTS) + if (AbstractDisassembler::show_structs()) { if (oop_maps != NULL) { ! tty->print("oop maps:"); // oop_maps->print_on(tty) outputs a cr() at the beginning ! oop_maps->print_on(tty); ! tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); ! } } + #endif + } else { + print(); // print the header part only. } + #if defined(SUPPORT_DATA_STRUCTS) + if (AbstractDisassembler::show_structs()) { if (PrintRelocations) { print_relocations(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); } + } + #endif if (xtty != NULL) { xtty->tail("print_native_nmethod"); } } }
*** 743,754 **** if (offsets->value(CodeOffsets::DeoptMH) != -1) { _deopt_mh_handler_begin = (address) this + code_offset() + offsets->value(CodeOffsets::DeoptMH); } else { _deopt_mh_handler_begin = NULL; } ! } else { #endif // Exception handler and deopt handler are in the stub section assert(offsets->value(CodeOffsets::Exceptions) != -1, "must be set"); assert(offsets->value(CodeOffsets::Deopt ) != -1, "must be set"); _exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions); --- 761,773 ---- if (offsets->value(CodeOffsets::DeoptMH) != -1) { _deopt_mh_handler_begin = (address) this + code_offset() + offsets->value(CodeOffsets::DeoptMH); } else { _deopt_mh_handler_begin = NULL; } ! } else #endif + { // Exception handler and deopt handler are in the stub section assert(offsets->value(CodeOffsets::Exceptions) != -1, "must be set"); assert(offsets->value(CodeOffsets::Deopt ) != -1, "must be set"); _exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions);
*** 756,768 **** if (offsets->value(CodeOffsets::DeoptMH) != -1) { _deopt_mh_handler_begin = (address) this + _stub_offset + offsets->value(CodeOffsets::DeoptMH); } else { _deopt_mh_handler_begin = NULL; } - #if INCLUDE_JVMCI } - #endif if (offsets->value(CodeOffsets::UnwindHandler) != -1) { _unwind_handler_offset = code_offset() + offsets->value(CodeOffsets::UnwindHandler); } else { _unwind_handler_offset = -1; } --- 775,785 ----
*** 784,794 **** #endif _entry_point = code_begin() + offsets->value(CodeOffsets::Entry); _verified_entry_point = code_begin() + offsets->value(CodeOffsets::Verified_Entry); _osr_entry_point = code_begin() + offsets->value(CodeOffsets::OSR_Entry); _exception_cache = NULL; - _scopes_data_begin = (address) this + scopes_data_offset; _pc_desc_container.reset_to(scopes_pcs_begin()); code_buffer->copy_code_and_locs_to(this); --- 801,810 ----
*** 906,942 **** if (xtty != NULL) { xtty->begin_head("print_nmethod"); xtty->stamp(); xtty->end_head(); } ! // print the header part first ! print(); ! // then print the requested information if (printmethod) { ! print_code(); print_pcs(); ! if (oop_maps()) { ! oop_maps()->print(); } } if (printmethod || PrintDebugInfo || CompilerOracle::has_option_string(_method, "PrintDebugInfo")) { print_scopes(); } if (printmethod || PrintRelocations || CompilerOracle::has_option_string(_method, "PrintRelocations")) { print_relocations(); } if (printmethod || PrintDependencies || CompilerOracle::has_option_string(_method, "PrintDependencies")) { print_dependencies(); } if (printmethod || PrintExceptionHandlers) { print_handler_table(); print_nul_chk_table(); } if (printmethod) { print_recorded_oops(); print_recorded_metadata(); } if (xtty != NULL) { xtty->tail("print_nmethod"); } } --- 922,997 ---- if (xtty != NULL) { xtty->begin_head("print_nmethod"); xtty->stamp(); xtty->end_head(); } ! // Print the header part, then print the requested information. ! // This is both handled in decode2(). if (printmethod) { ! HandleMark hm; ! ResourceMark m; ! if (is_compiled_by_c1()) { ! tty->cr(); ! tty->print_cr("============================= C1-compiled nmethod =============================="); ! } ! if (is_compiled_by_jvmci()) { ! tty->cr(); ! tty->print_cr("=========================== JVMCI-compiled nmethod ============================="); ! } ! tty->print_cr("----------------------------------- Assembly -----------------------------------"); ! decode2(tty); ! #if defined(SUPPORT_DATA_STRUCTS) ! if (AbstractDisassembler::show_structs()) { ! // Print the oops from the underlying CodeBlob as well. ! tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); ! print_oops(tty); ! tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); ! print_metadata(tty); ! tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); print_pcs(); ! tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); ! if (oop_maps() != NULL) { ! tty->print("oop maps:"); // oop_maps()->print_on(tty) outputs a cr() at the beginning ! oop_maps()->print_on(tty); ! tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); ! } } + #endif + } else { + print(); // print the header part only. } + + #if defined(SUPPORT_DATA_STRUCTS) + if (AbstractDisassembler::show_structs()) { if (printmethod || PrintDebugInfo || CompilerOracle::has_option_string(_method, "PrintDebugInfo")) { print_scopes(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); } if (printmethod || PrintRelocations || CompilerOracle::has_option_string(_method, "PrintRelocations")) { print_relocations(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); } if (printmethod || PrintDependencies || CompilerOracle::has_option_string(_method, "PrintDependencies")) { print_dependencies(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); } if (printmethod || PrintExceptionHandlers) { print_handler_table(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); print_nul_chk_table(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); } + if (printmethod) { print_recorded_oops(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); print_recorded_metadata(); + tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); } + } + #endif + if (xtty != NULL) { xtty->tail("print_nmethod"); } }
*** 2060,2084 **** ResourceMark rm(thread); CodeBlob* cb = CodeCache::find_blob(pc); assert(cb != NULL && cb == this, ""); ttyLocker ttyl; tty->print_cr("implicit exception happened at " INTPTR_FORMAT, p2i(pc)); ! print(); method()->print_codes(); - print_code(); - print_pcs(); } #endif if (cont_offset == 0) { // Let the normal error handling report the exception return NULL; } return code_begin() + cont_offset; } - void nmethod_init() { // make sure you didn't forget to adjust the filler fields assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word"); } --- 2115,2137 ---- ResourceMark rm(thread); CodeBlob* cb = CodeCache::find_blob(pc); assert(cb != NULL && cb == this, ""); ttyLocker ttyl; tty->print_cr("implicit exception happened at " INTPTR_FORMAT, p2i(pc)); ! // Print all available nmethod info. ! print_nmethod(true); method()->print_codes(); } #endif if (cont_offset == 0) { // Let the normal error handling report the exception return NULL; } return code_begin() + cont_offset; } void nmethod_init() { // make sure you didn't forget to adjust the filler fields assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word"); }
*** 2122,2137 **** public: VerifyOopsClosure(nmethod* nm) : _nm(nm), _ok(true) { } bool ok() { return _ok; } virtual void do_oop(oop* p) { if (oopDesc::is_oop_or_null(*p)) return; if (_ok) { _nm->print_nmethod(true); _ok = false; } - tty->print_cr("*** non-oop " PTR_FORMAT " found at " PTR_FORMAT " (offset %d)", - p2i(*p), p2i(p), (int)((intptr_t)p - (intptr_t)_nm)); } virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; void nmethod::verify() { --- 2175,2192 ---- public: VerifyOopsClosure(nmethod* nm) : _nm(nm), _ok(true) { } bool ok() { return _ok; } virtual void do_oop(oop* p) { if (oopDesc::is_oop_or_null(*p)) return; + // Print diagnostic information before calling print_nmethod(). + // Assertions therein might prevent call from returning. + tty->print_cr("*** non-oop " PTR_FORMAT " found at " PTR_FORMAT " (offset %d)", + p2i(*p), p2i(p), (int)((intptr_t)p - (intptr_t)_nm)); if (_ok) { _nm->print_nmethod(true); _ok = false; } } virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; void nmethod::verify() {
*** 2236,2346 **** // ----------------------------------------------------------------------------- // Printing operations void nmethod::print() const { - ResourceMark rm; ttyLocker ttyl; // keep the following output all in one block ! tty->print("Compiled method "); if (is_compiled_by_c1()) { ! tty->print("(c1) "); } else if (is_compiled_by_c2()) { ! tty->print("(c2) "); } else if (is_compiled_by_jvmci()) { ! tty->print("(JVMCI) "); } else { ! tty->print("(nm) "); } print_on(tty, NULL); if (WizardMode) { ! tty->print("((nmethod*) " INTPTR_FORMAT ") ", p2i(this)); ! tty->print(" for method " INTPTR_FORMAT , p2i(method())); ! tty->print(" { "); ! tty->print_cr("%s ", state()); ! tty->print_cr("}:"); } ! if (size () > 0) tty->print_cr(" total in heap [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(this), p2i(this) + size(), size()); ! if (relocation_size () > 0) tty->print_cr(" relocation [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(relocation_begin()), p2i(relocation_end()), relocation_size()); ! if (consts_size () > 0) tty->print_cr(" constants [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(consts_begin()), p2i(consts_end()), consts_size()); ! if (insts_size () > 0) tty->print_cr(" main code [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(insts_begin()), p2i(insts_end()), insts_size()); ! if (stub_size () > 0) tty->print_cr(" stub code [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(stub_begin()), p2i(stub_end()), stub_size()); ! if (oops_size () > 0) tty->print_cr(" oops [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(oops_begin()), p2i(oops_end()), oops_size()); ! if (metadata_size () > 0) tty->print_cr(" metadata [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(metadata_begin()), p2i(metadata_end()), metadata_size()); ! if (scopes_data_size () > 0) tty->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) tty->print_cr(" scopes pcs [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(scopes_pcs_begin()), p2i(scopes_pcs_end()), scopes_pcs_size()); ! if (dependencies_size () > 0) tty->print_cr(" dependencies [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(dependencies_begin()), p2i(dependencies_end()), dependencies_size()); ! if (handler_table_size() > 0) tty->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) tty->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 INCLUDE_JVMCI ! if (speculations_size () > 0) tty->print_cr(" speculations [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(speculations_begin()), p2i(speculations_end()), speculations_size()); ! if (jvmci_data_size () > 0) tty->print_cr(" JVMCI data [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(jvmci_data_begin()), p2i(jvmci_data_end()), jvmci_data_size()); #endif } ! #ifndef PRODUCT ! ! void nmethod::print_scopes() { ! // Find the first pc desc for all scopes in the code and print it. ! ResourceMark rm; ! for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) { ! if (p->scope_decode_offset() == DebugInformationRecorder::serialized_null) ! continue; ! ! ScopeDesc* sd = scope_desc_at(p->real_pc(this)); ! while (sd != NULL) { ! sd->print_on(tty, p); ! sd = sd->sender(); ! } ! } } void nmethod::print_dependencies() { ResourceMark rm; ttyLocker ttyl; // keep the following output all in one block tty->print_cr("Dependencies:"); for (Dependencies::DepStream deps(this); deps.next(); ) { --- 2291,2398 ---- // ----------------------------------------------------------------------------- // Printing operations void nmethod::print() const { ttyLocker ttyl; // keep the following output all in one block + print(tty); + } + + void nmethod::print(outputStream* st) const { + ResourceMark rm; ! st->print("Compiled method "); if (is_compiled_by_c1()) { ! st->print("(c1) "); } else if (is_compiled_by_c2()) { ! st->print("(c2) "); } else if (is_compiled_by_jvmci()) { ! st->print("(JVMCI) "); } else { ! st->print("(n/a) "); } print_on(tty, NULL); if (WizardMode) { ! st->print("((nmethod*) " INTPTR_FORMAT ") ", p2i(this)); ! st->print(" for method " INTPTR_FORMAT , p2i(method())); ! st->print(" { "); ! st->print_cr("%s ", state()); ! st->print_cr("}:"); } ! if (size () > 0) st->print_cr(" total in heap [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(this), p2i(this) + size(), size()); ! if (relocation_size () > 0) st->print_cr(" relocation [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(relocation_begin()), p2i(relocation_end()), relocation_size()); ! if (consts_size () > 0) st->print_cr(" constants [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(consts_begin()), p2i(consts_end()), consts_size()); ! if (insts_size () > 0) st->print_cr(" main code [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(insts_begin()), p2i(insts_end()), insts_size()); ! if (stub_size () > 0) st->print_cr(" stub code [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(stub_begin()), p2i(stub_end()), stub_size()); ! if (oops_size () > 0) st->print_cr(" oops [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", p2i(oops_begin()), p2i(oops_end()), oops_size()); ! if (metadata_size () > 0) st->print_cr(" metadata [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d", 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 (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 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 } ! void nmethod::print_code() { ! HandleMark hm; ! ResourceMark m; ! ttyLocker ttyl; ! // Call the specialized decode method of this class. ! decode(tty); } + #ifndef PRODUCT // called InstanceKlass methods are available only then. Declared as PRODUCT_RETURN + void nmethod::print_dependencies() { ResourceMark rm; ttyLocker ttyl; // keep the following output all in one block tty->print_cr("Dependencies:"); for (Dependencies::DepStream deps(this); deps.next(); ) {
*** 2352,2422 **** } } deps.log_dependency(); // put it into the xml log also } } void nmethod::print_relocations() { ResourceMark m; // in case methods get printed via the debugger tty->print_cr("relocations:"); RelocIterator iter(this); iter.print(); } ! ! void nmethod::print_pcs() { ResourceMark m; // in case methods get printed via debugger ! tty->print_cr("pc-bytecode offsets:"); for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) { ! p->print(this); } } void nmethod::print_recorded_oops() { ! tty->print_cr("Recorded oops:"); ! for (int i = 0; i < oops_count(); i++) { oop o = oop_at(i); ! tty->print("#%3d: " INTPTR_FORMAT " ", i, p2i(o)); ! if (o == Universe::non_oop_word()) { tty->print("non-oop word"); } else { ! if (o != NULL) { ! o->print_value(); ! } else { ! tty->print_cr("NULL"); ! } } tty->cr(); } } void nmethod::print_recorded_metadata() { ! tty->print_cr("Recorded metadata:"); ! for (int i = 0; i < metadata_count(); i++) { Metadata* m = metadata_at(i); ! tty->print("#%3d: " INTPTR_FORMAT " ", i, p2i(m)); if (m == (Metadata*)Universe::non_oop_word()) { tty->print("non-metadata word"); } else { Metadata::print_value_on_maybe_null(tty, m); } tty->cr(); } } ! #endif // PRODUCT const char* nmethod::reloc_string_for(u_char* begin, u_char* end) { RelocIterator iter(this, begin, end); bool have_one = false; while (iter.next()) { have_one = true; switch (iter.type()) { case relocInfo::none: return "no_reloc"; case relocInfo::oop_type: { ! stringStream st; oop_Relocation* r = iter.oop_reloc(); oop obj = r->oop_value(); st.print("oop("); if (obj == NULL) st.print("NULL"); else obj->print_value_on(&st); --- 2404,2798 ---- } } deps.log_dependency(); // put it into the xml log also } } + #endif + + #if defined(SUPPORT_DATA_STRUCTS) + + // Print the oops from the underlying CodeBlob. + void nmethod::print_oops(outputStream* st) { + HandleMark hm; + ResourceMark m; + st->print("Oops:"); + if (oops_begin() < oops_end()) { + st->cr(); + for (oop* p = oops_begin(); p < oops_end(); p++) { + Disassembler::print_location((unsigned char*)p, (unsigned char*)oops_begin(), (unsigned char*)oops_end(), st, true, false); + st->print(PTR64_FORMAT " ", *((unsigned long*)p)); + if (*p == Universe::non_oop_word()) { + st->print_cr("NON_OOP"); + continue; // skip non-oops + } + if (*p == NULL) { + st->print_cr("NULL-oop"); + continue; // skip non-oops + } + (*p)->print_value_on(st); + st->cr(); + } + } else { + st->print_cr(" <list empty>"); + } + } + + // Print metadata pool. + void nmethod::print_metadata(outputStream* st) { + HandleMark hm; + ResourceMark m; + st->print("Metadata:"); + if (metadata_begin() < metadata_end()) { + st->cr(); + for (Metadata** p = metadata_begin(); p < metadata_end(); p++) { + Disassembler::print_location((unsigned char*)p, (unsigned char*)metadata_begin(), (unsigned char*)metadata_end(), st, true, false); + st->print(PTR64_FORMAT " ", *((unsigned long*)p)); + if (*p && *p != Universe::non_oop_word()) { + (*p)->print_value_on(st); + } + st->cr(); + } + } else { + st->print_cr(" <list empty>"); + } + } + + #ifndef PRODUCT // ScopeDesc::print_on() is available only then. Declared as PRODUCT_RETURN + void nmethod::print_scopes_on(outputStream* st) { + // Find the first pc desc for all scopes in the code and print it. + ResourceMark rm; + st->print("scopes:"); + if (scopes_pcs_begin() < scopes_pcs_end()) { + st->cr(); + for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) { + if (p->scope_decode_offset() == DebugInformationRecorder::serialized_null) + continue; + ScopeDesc* sd = scope_desc_at(p->real_pc(this)); + while (sd != NULL) { + sd->print_on(st, p); // print output ends with a newline + sd = sd->sender(); + } + } + } else { + st->print_cr(" <list empty>"); + } + } + #endif + #ifndef PRODUCT // RelocIterator does support printing only then. void nmethod::print_relocations() { ResourceMark m; // in case methods get printed via the debugger tty->print_cr("relocations:"); RelocIterator iter(this); iter.print(); } + #endif ! void nmethod::print_pcs_on(outputStream* st) { ResourceMark m; // in case methods get printed via debugger ! st->print("pc-bytecode offsets:"); ! if (scopes_pcs_begin() < scopes_pcs_end()) { ! st->cr(); for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) { ! p->print_on(st, this); // print output ends with a newline } + } else { + st->print_cr(" <list empty>"); + } + } + + void nmethod::print_handler_table() { + ExceptionHandlerTable(this).print(); + } + + void nmethod::print_nul_chk_table() { + ImplicitExceptionTable(this).print(code_begin()); } void nmethod::print_recorded_oops() { ! const int n = oops_count(); ! const int log_n = (n<10) ? 1 : (n<100) ? 2 : (n<1000) ? 3 : (n<10000) ? 4 : 6; ! tty->print("Recorded oops:"); ! if (n > 0) { ! tty->cr(); ! for (int i = 0; i < n; i++) { oop o = oop_at(i); ! tty->print("#%*d: " INTPTR_FORMAT " ", log_n, i, p2i(o)); ! if (o == (oop)Universe::non_oop_word()) { tty->print("non-oop word"); + } else if (o == NULL) { + tty->print("NULL-oop"); } else { ! o->print_value_on(tty); } tty->cr(); } + } else { + tty->print_cr(" <list empty>"); + } } void nmethod::print_recorded_metadata() { ! const int n = metadata_count(); ! const int log_n = (n<10) ? 1 : (n<100) ? 2 : (n<1000) ? 3 : (n<10000) ? 4 : 6; ! tty->print("Recorded metadata:"); ! if (n > 0) { ! tty->cr(); ! for (int i = 0; i < n; i++) { Metadata* m = metadata_at(i); ! tty->print("#%*d: " INTPTR_FORMAT " ", log_n, i, p2i(m)); if (m == (Metadata*)Universe::non_oop_word()) { tty->print("non-metadata word"); + } else if (m == NULL) { + tty->print("NULL-oop"); } else { Metadata::print_value_on_maybe_null(tty, m); } tty->cr(); } + } else { + tty->print_cr(" <list empty>"); + } + } + #endif + + #if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY) + + void nmethod::print_constant_pool(outputStream* st) { + //----------------------------------- + //---< Print the constant pool >--- + //----------------------------------- + int consts_size = this->consts_size(); + if ( consts_size > 0 ) { + unsigned char* cstart = this->consts_begin(); + unsigned char* cp = cstart; + unsigned char* cend = cp + consts_size; + unsigned int bytes_per_line = 4; + unsigned int CP_alignment = 8; + unsigned int n; + + st->cr(); + + //---< print CP header to make clear what's printed >--- + if( ((uintptr_t)cp&(CP_alignment-1)) == 0 ) { + n = bytes_per_line; + st->print_cr("[Constant Pool]"); + Disassembler::print_location(cp, cstart, cend, st, true, true); + Disassembler::print_hexdata(cp, n, st, true); + st->cr(); + } else { + n = (uintptr_t)cp&(bytes_per_line-1); + st->print_cr("[Constant Pool (unaligned)]"); + } + + //---< print CP contents, bytes_per_line at a time >--- + while (cp < cend) { + Disassembler::print_location(cp, cstart, cend, st, true, false); + Disassembler::print_hexdata(cp, n, st, false); + cp += n; + n = bytes_per_line; + st->cr(); + } + + //---< Show potential alignment gap between constant pool and code >--- + cend = code_begin(); + if( cp < cend ) { + n = 4; + st->print_cr("[Code entry alignment]"); + while (cp < cend) { + Disassembler::print_location(cp, cstart, cend, st, false, false); + cp += n; + st->cr(); + } + } + } else { + st->print_cr("[Constant Pool (empty)]"); + } + st->cr(); } ! #endif ! ! // Disassemble this nmethod. ! // Print additional debug information, if requested. This could be code ! // comments, block comments, profiling counters, etc. ! // The undisassembled format is useful no disassembler library is available. ! // The resulting hex dump (with markers) can be disassembled later, or on ! // another system, when/where a disassembler library is available. ! void nmethod::decode2(outputStream* ost) const { ! ! // Called from frame::back_trace_with_decode without ResourceMark. ! ResourceMark rm; ! ! // Make sure we have a valid stream to print on. ! outputStream* st = ost ? ost : tty; ! ! #if defined(SUPPORT_ABSTRACT_ASSEMBLY) && ! defined(SUPPORT_ASSEMBLY) ! const bool use_compressed_format = true; ! const bool compressed_with_comments = use_compressed_format && (AbstractDisassembler::show_comment() || ! AbstractDisassembler::show_block_comment()); ! #else ! const bool use_compressed_format = Disassembler::is_abstract(); ! const bool compressed_with_comments = use_compressed_format && (AbstractDisassembler::show_comment() || ! AbstractDisassembler::show_block_comment()); ! #endif ! ! st->cr(); ! this->print(st); ! st->cr(); ! ! #if defined(SUPPORT_ASSEMBLY) ! //---------------------------------- ! //---< Print real disassembly >--- ! //---------------------------------- ! if (! use_compressed_format) { ! Disassembler::decode(const_cast<nmethod*>(this), st); ! return; ! } ! #endif ! ! #if defined(SUPPORT_ABSTRACT_ASSEMBLY) ! ! // Compressed undisassembled disassembly format. ! // The following stati are defined/supported: ! // = 0 - currently at bol() position, nothing printed yet on current line. ! // = 1 - currently at position after print_location(). ! // > 1 - in the midst of printing instruction stream bytes. ! int compressed_format_idx = 0; ! int code_comment_column = 0; ! const int instr_maxlen = Assembler::instr_maxlen(); ! const uint tabspacing = 8; ! unsigned char* start = this->code_begin(); ! unsigned char* p = this->code_begin(); ! unsigned char* end = this->code_end(); ! unsigned char* pss = p; // start of a code section (used for offsets) ! ! if ((start == NULL) || (end == NULL)) { ! st->print_cr("PrintAssembly not possible due to uninitialized section pointers"); ! return; ! } ! #endif ! ! #if defined(SUPPORT_ABSTRACT_ASSEMBLY) ! //---< plain abstract disassembly, no comments or anything, just section headers >--- ! if (use_compressed_format && ! compressed_with_comments) { ! const_cast<nmethod*>(this)->print_constant_pool(st); ! ! //---< Open the output (Marker for post-mortem disassembler) >--- ! st->print_cr("[MachCode]"); ! const char* header = NULL; ! address p0 = p; ! while (p < end) { ! address pp = p; ! while ((p < end) && (header == NULL)) { ! header = nmethod_section_label(p); ! pp = p; ! p += Assembler::instr_len(p); ! } ! if (pp > p0) { ! AbstractDisassembler::decode_range_abstract(p0, pp, start, end, st, Assembler::instr_maxlen()); ! p0 = pp; ! p = pp; ! header = NULL; ! } else if (header != NULL) { ! st->bol(); ! st->print_cr("%s", header); ! header = NULL; ! } ! } ! //---< Close the output (Marker for post-mortem disassembler) >--- ! st->bol(); ! st->print_cr("[/MachCode]"); ! return; ! } ! #endif ! ! #if defined(SUPPORT_ABSTRACT_ASSEMBLY) ! //---< abstract disassembly with comments and section headers merged in >--- ! if (compressed_with_comments) { ! const_cast<nmethod*>(this)->print_constant_pool(st); ! ! //---< Open the output (Marker for post-mortem disassembler) >--- ! st->print_cr("[MachCode]"); ! while ((p < end) && (p != NULL)) { ! const int instruction_size_in_bytes = Assembler::instr_len(p); ! ! //---< Block comments for nmethod. Interrupts instruction stream, if any. >--- ! // Outputs a bol() before and a cr() after, but only if a comment is printed. ! // Prints nmethod_section_label as well. ! if (AbstractDisassembler::show_block_comment()) { ! print_block_comment(st, p); ! if (st->position() == 0) { ! compressed_format_idx = 0; ! } ! } ! ! //---< New location information after line break >--- ! if (compressed_format_idx == 0) { ! code_comment_column = Disassembler::print_location(p, pss, end, st, false, false); ! compressed_format_idx = 1; ! } ! ! //---< Code comment for current instruction. Address range [p..(p+len)) >--- ! unsigned char* p_end = p + (ssize_t)instruction_size_in_bytes; ! S390_ONLY(if (p_end > end) p_end = end;) // avoid getting past the end ! ! if (AbstractDisassembler::show_comment() && const_cast<nmethod*>(this)->has_code_comment(p, p_end)) { ! //---< interrupt instruction byte stream for code comment >--- ! if (compressed_format_idx > 1) { ! st->cr(); // interrupt byte stream ! st->cr(); // add an empty line ! code_comment_column = Disassembler::print_location(p, pss, end, st, false, false); ! } ! const_cast<nmethod*>(this)->print_code_comment_on(st, code_comment_column, p, p_end ); ! st->bol(); ! compressed_format_idx = 0; ! } ! ! //---< New location information after line break >--- ! if (compressed_format_idx == 0) { ! code_comment_column = Disassembler::print_location(p, pss, end, st, false, false); ! compressed_format_idx = 1; ! } ! ! //---< Nicely align instructions for readability >--- ! if (compressed_format_idx > 1) { ! Disassembler::print_delimiter(st); ! } ! ! //---< Now, finally, print the actual instruction bytes >--- ! unsigned char* p0 = p; ! p = Disassembler::decode_instruction_abstract(p, st, instruction_size_in_bytes, instr_maxlen); ! compressed_format_idx += p - p0; ! ! if (Disassembler::start_newline(compressed_format_idx-1)) { ! st->cr(); ! compressed_format_idx = 0; ! } ! } ! //---< Close the output (Marker for post-mortem disassembler) >--- ! st->bol(); ! st->print_cr("[/MachCode]"); ! return; ! } ! #endif ! } ! ! #if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY) const char* nmethod::reloc_string_for(u_char* begin, u_char* end) { RelocIterator iter(this, begin, end); bool have_one = false; while (iter.next()) { have_one = true; switch (iter.type()) { case relocInfo::none: return "no_reloc"; case relocInfo::oop_type: { ! // Get a non-resizable resource-allocated stringStream. ! // Our callees make use of (nested) ResourceMarks. ! stringStream st(NEW_RESOURCE_ARRAY(char, 1024), 1024); oop_Relocation* r = iter.oop_reloc(); oop obj = r->oop_value(); st.print("oop("); if (obj == NULL) st.print("NULL"); else obj->print_value_on(&st);
*** 2514,2534 **** p->return_oop()); } return NULL; } ! void nmethod::print_nmethod_labels(outputStream* stream, address block_begin) const { ! if (block_begin == entry_point()) stream->print_cr("[Entry Point]"); ! if (block_begin == verified_entry_point()) stream->print_cr("[Verified Entry Point]"); ! if (JVMCI_ONLY(_exception_offset >= 0 &&) block_begin == exception_begin()) stream->print_cr("[Exception Handler]"); ! if (block_begin == stub_begin()) stream->print_cr("[Stub Code]"); ! if (JVMCI_ONLY(_deopt_handler_begin != NULL &&) block_begin == deopt_handler_begin()) stream->print_cr("[Deopt Handler Code]"); ! ! if (has_method_handle_invokes()) ! if (block_begin == deopt_mh_handler_begin()) stream->print_cr("[Deopt MH Handler Code]"); ! ! if (block_begin == consts_begin()) stream->print_cr("[Constants]"); if (block_begin == entry_point()) { methodHandle m = method(); if (m.not_null()) { stream->print(" # "); --- 2890,2921 ---- p->return_oop()); } return NULL; } ! const char* nmethod::nmethod_section_label(address pos) const { ! const char* label = NULL; ! if (pos == code_begin()) label = "[Instructions begin]"; ! if (pos == entry_point()) label = "[Entry Point]"; ! if (pos == verified_entry_point()) label = "[Verified Entry Point]"; ! if (has_method_handle_invokes() && (pos == deopt_mh_handler_begin())) label = "[Deopt MH Handler Code]"; ! if (pos == consts_begin() && pos != insts_begin()) label = "[Constants]"; ! // Check stub_code before checking exception_handler or deopt_handler. ! if (pos == this->stub_begin()) label = "[Stub Code]"; ! if (JVMCI_ONLY(_exception_offset >= 0 &&) pos == exception_begin()) label = "[Exception Handler]"; ! if (JVMCI_ONLY(_deopt_handler_begin != NULL &&) pos == deopt_handler_begin()) label = "[Deopt Handler Code]"; ! return label; ! } ! ! void nmethod::print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels) const { ! if (print_section_labels) { ! const char* label = nmethod_section_label(block_begin); ! if (label != NULL) { ! stream->bol(); ! stream->print_cr("%s", label); ! } ! } if (block_begin == entry_point()) { methodHandle m = method(); if (m.not_null()) { stream->print(" # ");
*** 2621,2631 **** } } } } ! void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin, u_char* end) { // First, find an oopmap in (begin, end]. // We use the odd half-closed interval so that oop maps and scope descs // which are tied to the byte after a call are printed with the call itself. address base = code_begin(); ImmutableOopMapSet* oms = oop_maps(); --- 3008,3035 ---- } } } } ! // Returns whether this nmethod has code comments. ! bool nmethod::has_code_comment(address begin, address end) { ! // scopes? ! ScopeDesc* sd = scope_desc_in(begin, end); ! if (sd != NULL) return true; ! ! // relocations? ! const char* str = reloc_string_for(begin, end); ! if (str != NULL) return true; ! ! // implicit exceptions? ! int cont_offset = ImplicitExceptionTable(this).at(begin - code_begin()); ! if (cont_offset != 0) return true; ! ! return false; ! } ! ! void nmethod::print_code_comment_on(outputStream* st, int column, address begin, address end) { // First, find an oopmap in (begin, end]. // We use the odd half-closed interval so that oop maps and scope descs // which are tied to the byte after a call are printed with the call itself. address base = code_begin(); ImmutableOopMapSet* oms = oop_maps();
*** 2634,2644 **** const ImmutableOopMapPair* pair = oms->pair_at(i); const ImmutableOopMap* om = pair->get_from(oms); address pc = base + pair->pc_offset(); if (pc > begin) { if (pc <= end) { ! st->move_to(column); st->print("; "); om->print_on(st); } break; } --- 3038,3048 ---- const ImmutableOopMapPair* pair = oms->pair_at(i); const ImmutableOopMap* om = pair->get_from(oms); address pc = base + pair->pc_offset(); if (pc > begin) { if (pc <= end) { ! st->move_to(column, 6, 0); st->print("; "); om->print_on(st); } break; }
*** 2646,2656 **** } // Print any debug info present at this pc. ScopeDesc* sd = scope_desc_in(begin, end); if (sd != NULL) { ! st->move_to(column); if (sd->bci() == SynchronizationEntryBCI) { st->print(";*synchronization entry"); } else if (sd->bci() == AfterBci) { st->print(";* method exit (unlocked if synchronized)"); } else if (sd->bci() == UnwindBci) { --- 3050,3060 ---- } // Print any debug info present at this pc. ScopeDesc* sd = scope_desc_in(begin, end); if (sd != NULL) { ! st->move_to(column, 6, 0); if (sd->bci() == SynchronizationEntryBCI) { st->print(";*synchronization entry"); } else if (sd->bci() == AfterBci) { st->print(";* method exit (unlocked if synchronized)"); } else if (sd->bci() == UnwindBci) {
*** 2702,2713 **** st->print(" {reexecute=%d rethrow=%d return_oop=%d}", sd->should_reexecute(), sd->rethrow_exception(), sd->return_oop()); } // Print all scopes for (;sd != NULL; sd = sd->sender()) { ! st->move_to(column); st->print("; -"); if (sd->method() == NULL) { st->print("method is NULL"); } else { sd->method()->print_short_name(st); } --- 3106,3120 ---- st->print(" {reexecute=%d rethrow=%d return_oop=%d}", sd->should_reexecute(), sd->rethrow_exception(), sd->return_oop()); } // Print all scopes for (;sd != NULL; sd = sd->sender()) { ! st->move_to(column, 6, 0); st->print("; -"); + if (sd->should_reexecute()) { + st->print(" (reexecute)"); + } if (sd->method() == NULL) { st->print("method is NULL"); } else { sd->method()->print_short_name(st); }
*** 2720,2743 **** st->cr(); } } // Print relocation information const char* str = reloc_string_for(begin, end); if (str != NULL) { if (sd != NULL) st->cr(); ! st->move_to(column); st->print("; {%s}", str); } int cont_offset = ImplicitExceptionTable(this).at(begin - code_begin()); if (cont_offset != 0) { ! st->move_to(column); st->print("; implicit exception: dispatches to " INTPTR_FORMAT, p2i(code_begin() + cont_offset)); } } class DirectNativeCallWrapper: public NativeCallWrapper { private: NativeCall* _call; public: --- 3127,3154 ---- st->cr(); } } // Print relocation information + // Prevent memory leak: allocating without ResourceMark. + ResourceMark rm; const char* str = reloc_string_for(begin, end); if (str != NULL) { if (sd != NULL) st->cr(); ! st->move_to(column, 6, 0); st->print("; {%s}", str); } int cont_offset = ImplicitExceptionTable(this).at(begin - code_begin()); if (cont_offset != 0) { ! st->move_to(column, 6, 0); st->print("; implicit exception: dispatches to " INTPTR_FORMAT, p2i(code_begin() + cont_offset)); } } + #endif + class DirectNativeCallWrapper: public NativeCallWrapper { private: NativeCall* _call; public:
*** 2840,2855 **** CompiledStaticCall* nmethod::compiledStaticCall_before(address return_addr) const { return CompiledDirectStaticCall::before(return_addr); } ! #ifndef PRODUCT ! void nmethod::print_value_on(outputStream* st) const { st->print("nmethod"); print_on(st, NULL); } void nmethod::print_calls(outputStream* st) { RelocIterator iter(this); while (iter.next()) { switch (iter.type()) { --- 3251,3268 ---- CompiledStaticCall* nmethod::compiledStaticCall_before(address return_addr) const { return CompiledDirectStaticCall::before(return_addr); } ! #if defined(SUPPORT_DATA_STRUCTS) void nmethod::print_value_on(outputStream* st) const { st->print("nmethod"); print_on(st, NULL); } + #endif + + #ifndef PRODUCT void nmethod::print_calls(outputStream* st) { RelocIterator iter(this); while (iter.next()) { switch (iter.type()) {
*** 2867,2884 **** break; } } } - void nmethod::print_handler_table() { - ExceptionHandlerTable(this).print(); - } - - void nmethod::print_nul_chk_table() { - ImplicitExceptionTable(this).print(code_begin()); - } - void nmethod::print_statistics() { ttyLocker ttyl; if (xtty != NULL) xtty->head("statistics type='nmethod'"); native_nmethod_stats.print_native_nmethod_stats(); #ifdef COMPILER1 --- 3280,3289 ----
< prev index next >