< prev index next > src/hotspot/share/code/nmethod.cpp
Print this page
#include "code/compiledIC.hpp"
#include "code/dependencies.hpp"
#include "code/nativeInst.hpp"
#include "code/nmethod.inline.hpp"
#include "code/scopeDesc.hpp"
+ #include "code/SCCache.hpp"
#include "compiler/abstractCompiler.hpp"
#include "compiler/compilationLog.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "compiler/compileTask.hpp"
klass = ((Klass*)md);
} else if (md->is_method()) {
klass = ((Method*)md)->method_holder();
} else if (md->is_methodData()) {
klass = ((MethodData*)md)->method()->method_holder();
+ } else if (md->is_methodCounters()) {
+ klass = ((MethodCounters*)md)->method()->method_holder();
} else {
md->print();
ShouldNotReachHere();
}
assert(klass->is_loader_alive(), "must be alive");
OopMapSet* oop_maps,
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
CompLevel comp_level
+ , SCCEntry* scc_entry
#if INCLUDE_JVMCI
, char* speculations,
int speculations_len,
JVMCINMethodData* jvmci_data
#endif
nm = new (nmethod_size, 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,
jvmci_data
#endif
nm = new (nmethod_size, 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, scc_entry
#if INCLUDE_JVMCI
, speculations,
speculations_len,
jvmci_data
#endif
NOT_PRODUCT(if (nm != nullptr) note_java_nmethod(nm));
}
}
// Do verification and logging outside CodeCache_lock.
if (nm != nullptr) {
+
+ #ifdef ASSERT
+ LogTarget(Debug, scc, nmethod) log;
+ if (log.is_enabled()) {
+ LogStream out(log);
+ out.print_cr("== new_nmethod 2");
+ FlagSetting fs(PrintRelocations, true);
+ nm->print(&out);
+ nm->decode(&out);
+ }
+ #endif
+
// Safepoints in nmethod::verify aren't allowed because nm hasn't been installed yet.
DEBUG_ONLY(nm->verify();)
nm->log_new_nmethod();
}
return nm;
_has_monitors = 0;
_has_scoped_access = 0;
_has_flushed_dependencies = 0;
_is_unlinked = 0;
_load_reported = 0; // jvmti state
+ _preloaded = 0;
+ _has_clinit_barriers = 0;
+ _used = false;
_deoptimization_status = not_marked;
// SECT_CONSTS is first in code buffer so the offset should be 0.
int consts_offset = code_buffer->total_offset_of(code_buffer->consts());
assert(consts_offset == 0, "const_offset: %d", consts_offset);
}
// Native wrappers do not have deopt handlers. Make the values
// something that will never match a pc like the nmethod vtable entry
_deopt_handler_offset = 0;
_deopt_mh_handler_offset = 0;
+ _scc_entry = nullptr;
+ _method_profiling_count = 0;
_unwind_handler_offset = 0;
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
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 != nullptr) {
print(); // print the header part only.
}
#if defined(SUPPORT_DATA_STRUCTS)
if (AbstractDisassembler::show_structs()) {
if (PrintRelocations) {
! print_relocations_on(tty);
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
}
}
#endif
if (xtty != nullptr) {
OopMapSet* oop_maps,
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
CompLevel comp_level
+ , SCCEntry* scc_entry
#if INCLUDE_JVMCI
, char* speculations,
int speculations_len,
JVMCINMethodData* jvmci_data
#endif
{
debug_only(NoSafepointVerifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
init_defaults(code_buffer, offsets);
+ _scc_entry = scc_entry;
+ _method_profiling_count = 0;
_osr_entry_point = code_begin() + offsets->value(CodeOffsets::OSR_Entry);
_entry_bci = entry_bci;
_compile_id = compile_id;
_comp_level = comp_level;
}
// Print a short set of xml attributes to identify this nmethod. The
// output should be embedded in some other element.
void nmethod::log_identity(xmlStream* log) const {
! log->print(" compile_id='%d'", compile_id());
const char* nm_kind = compile_kind();
! if (nm_kind != nullptr) log->print(" compile_kind='%s'", nm_kind);
! log->print(" compiler='%s'", compiler_name());
if (TieredCompilation) {
! log->print(" level='%d'", comp_level());
}
#if INCLUDE_JVMCI
if (jvmci_nmethod_data() != nullptr) {
const char* jvmci_name = jvmci_nmethod_data()->name();
if (jvmci_name != nullptr) {
}
// Print a short set of xml attributes to identify this nmethod. The
// output should be embedded in some other element.
void nmethod::log_identity(xmlStream* log) const {
! assert(log->inside_attrs_or_error(), "printing attributes");
+ log->print(" code_compile_id='%d'", compile_id());
const char* nm_kind = compile_kind();
! if (nm_kind != nullptr) log->print(" code_compile_kind='%s'", nm_kind);
! log->print(" code_compiler='%s'", compiler_name());
if (TieredCompilation) {
! log->print(" code_compile_level='%d'", comp_level());
}
#if INCLUDE_JVMCI
if (jvmci_nmethod_data() != nullptr) {
const char* jvmci_name = jvmci_nmethod_data()->name();
if (jvmci_name != nullptr) {
if (printmethod || PrintDebugInfo || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDebugInfo)) {
print_scopes();
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
}
if (printmethod || PrintRelocations || CompilerOracle::has_option(mh, CompileCommandEnum::PrintRelocations)) {
! print_relocations();
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
}
if (printmethod || PrintDependencies || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDependencies)) {
print_dependencies_on(tty);
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
if (printmethod || PrintDebugInfo || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDebugInfo)) {
print_scopes();
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
}
if (printmethod || PrintRelocations || CompilerOracle::has_option(mh, CompileCommandEnum::PrintRelocations)) {
! print_relocations_on(tty);
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
}
if (printmethod || PrintDependencies || CompilerOracle::has_option(mh, CompileCommandEnum::PrintDependencies)) {
print_dependencies_on(tty);
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
if (mdo == nullptr) return;
// There is a benign race here. See comments in methodData.hpp.
mdo->inc_decompile_count();
}
+ void nmethod::inc_method_profiling_count() {
+ Atomic::inc(&_method_profiling_count);
+ }
+
+ uint64_t nmethod::method_profiling_count() {
+ return _method_profiling_count;
+ }
+
bool nmethod::try_transition(signed char new_state_int) {
signed char new_state = new_state_int;
assert_lock_strong(NMethodState_lock);
signed char old_state = _state;
if (old_state >= new_state) {
method()->unlink_code(this);
}
}
// Invalidate code
! bool nmethod::make_not_entrant() {
// This can be called while the system is already at a safepoint which is ok
NoSafepointVerifier nsv;
if (is_unloading()) {
// If the nmethod is unloading, then it is already not entrant through
method()->unlink_code(this);
}
}
// Invalidate code
! bool nmethod::make_not_entrant(bool make_not_entrant) {
// This can be called while the system is already at a safepoint which is ok
NoSafepointVerifier nsv;
if (is_unloading()) {
// If the nmethod is unloading, then it is already not entrant through
log_state_change();
// Remove nmethod from method.
unlink_from_method();
+ if (make_not_entrant) {
+ // Keep cached code if it was simply replaced
+ // otherwise make it not entrant too.
+ SCCache::invalidate(_scc_entry);
+ }
+
+ CompileBroker::log_not_entrant(this);
} // leave critical region under NMethodState_lock
#if INCLUDE_JVMCI
// Invalidate can't occur while holding the NMethodState_lock
JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
task->mark_success();
task->set_nm_content_size(content_size());
task->set_nm_insts_size(insts_size());
task->set_nm_total_size(total_size());
+ // task->is_scc() is true only for loaded cached code.
+ // nmethod::_scc_entry is set for loaded and stored cached code
+ // to invalidate the entry when nmethod is deoptimized.
+ // There is option to not store in archive cached code.
+ guarantee((_scc_entry != nullptr) || !task->is_scc() || VerifyCachedCode, "sanity");
+
// JVMTI -- compiled method notification (must be done outside lock)
post_compiled_method_load_event();
if (CompilationLog::log() != nullptr) {
CompilationLog::log()->log_nmethod(JavaThread::current(), this);
if (speculations_size () > 0) st->print_cr(" speculations [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
p2i(speculations_begin()),
p2i(speculations_end()),
speculations_size());
#endif
+ if (SCCache::is_on() && _scc_entry != nullptr) {
+ _scc_entry->print(st);
+ }
}
void nmethod::print_code() {
ResourceMark m;
ttyLocker ttyl;
}
}
#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
}
}
#endif
#ifndef PRODUCT // RelocIterator does support printing only then.
! void nmethod::print_relocations_on(outputStream* st) {
ResourceMark m; // in case methods get printed via the debugger
! st->print_cr("relocations:");
RelocIterator iter(this);
! iter.print_on(st);
}
#endif
void nmethod::print_pcs_on(outputStream* st) {
ResourceMark m; // in case methods get printed via debugger
case relocInfo::runtime_call_w_cp_type: {
stringStream st;
st.print("runtime_call");
CallRelocation* r = (CallRelocation*)iter.reloc();
address dest = r->destination();
+ if (StubRoutines::contains(dest)) {
+ StubCodeDesc* desc = StubCodeDesc::desc_for(dest);
+ if (desc == nullptr) {
+ desc = StubCodeDesc::desc_for(dest + frame::pc_return_offset);
+ }
+ if (desc != nullptr) {
+ st.print(" Stub::%s", desc->name());
+ return st.as_string();
+ }
+ }
CodeBlob* cb = CodeCache::find_blob(dest);
if (cb != nullptr) {
st.print(" %s", cb->name());
} else {
ResourceMark rm;
< prev index next >