diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index d7a9c8d56d430..42c9d72edcb0e 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -800,7 +800,7 @@ JRT_ENTRY(void, Runtime1::deoptimize(JavaThread* current, jint trap_request)) Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request); if (action == Deoptimization::Action_make_not_entrant) { - if (nm->make_not_entrant("C1 deoptimize")) { + if (nm->make_not_entrant(nmethod::ChangeReason::C1_deoptimize)) { if (reason == Deoptimization::Reason_tenured) { MethodData* trap_mdo = Deoptimization::get_method_data(current, method, true /*create_if_missing*/); if (trap_mdo != nullptr) { @@ -1092,7 +1092,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) // safepoint, but if it's still alive then make it not_entrant. nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); if (nm != nullptr) { - nm->make_not_entrant("C1 code patch"); + nm->make_not_entrant(nmethod::ChangeReason::C1_codepatch); } Deoptimization::deoptimize_frame(current, caller_frame.id()); @@ -1340,7 +1340,7 @@ void Runtime1::patch_code(JavaThread* current, C1StubId stub_id) { // Make sure the nmethod is invalidated, i.e. made not entrant. nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); if (nm != nullptr) { - nm->make_not_entrant("C1 deoptimize for patching"); + nm->make_not_entrant(nmethod::ChangeReason::C1_deoptimize_for_patching); } } @@ -1468,7 +1468,7 @@ JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* current)) nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); assert (nm != nullptr, "no more nmethod?"); - nm->make_not_entrant("C1 predicate failed trap"); + nm->make_not_entrant(nmethod::ChangeReason::C1_predicate_failed_trap); methodHandle m(current, nm->method()); MethodData* mdo = m->method_data(); diff --git a/src/hotspot/share/ci/ciReplay.cpp b/src/hotspot/share/ci/ciReplay.cpp index d490b75919d2a..04b4367a99f4c 100644 --- a/src/hotspot/share/ci/ciReplay.cpp +++ b/src/hotspot/share/ci/ciReplay.cpp @@ -802,7 +802,7 @@ class CompileReplay : public StackObj { // Make sure the existence of a prior compile doesn't stop this one nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code(); if (nm != nullptr) { - nm->make_not_entrant("CI replay"); + nm->make_not_entrant(nmethod::ChangeReason::CI_replay); } replay_state = this; CompileBroker::compile_method(methodHandle(THREAD, method), entry_bci, comp_level, diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 902d434562229..3a5da1d7cd2ae 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1361,7 +1361,7 @@ void CodeCache::make_marked_nmethods_deoptimized() { while(iter.next()) { nmethod* nm = iter.method(); if (nm->is_marked_for_deoptimization() && !nm->has_been_deoptimized() && nm->can_be_deoptimized()) { - nm->make_not_entrant("marked for deoptimization"); + nm->make_not_entrant(nmethod::ChangeReason::marked_for_deoptimization); nm->make_deoptimized(); } } diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 01ace66f4dee4..7ad1a47550ac3 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1964,14 +1964,12 @@ void nmethod::invalidate_osr_method() { } } -void nmethod::log_state_change(const char* reason) const { - assert(reason != nullptr, "Must provide a reason"); - +void nmethod::log_state_change(ChangeReason change_reason) const { if (LogCompilation) { if (xtty != nullptr) { ttyLocker ttyl; // keep the following output all in one block xtty->begin_elem("make_not_entrant thread='%zu' reason='%s'", - os::current_thread_id(), reason); + os::current_thread_id(), change_reason_to_string(change_reason)); log_identity(xtty); xtty->stamp(); xtty->end_elem(); @@ -1980,7 +1978,7 @@ void nmethod::log_state_change(const char* reason) const { ResourceMark rm; stringStream ss(NEW_RESOURCE_ARRAY(char, 256), 256); - ss.print("made not entrant: %s", reason); + ss.print("made not entrant: %s", change_reason_to_string(change_reason)); CompileTask::print_ul(this, ss.freeze()); if (PrintCompilation) { @@ -1995,9 +1993,7 @@ void nmethod::unlink_from_method() { } // Invalidate code -bool nmethod::make_not_entrant(const char* reason) { - assert(reason != nullptr, "Must provide a reason"); - +bool nmethod::make_not_entrant(ChangeReason change_reason) { // This can be called while the system is already at a safepoint which is ok NoSafepointVerifier nsv; @@ -2055,7 +2051,7 @@ bool nmethod::make_not_entrant(const char* reason) { assert(success, "Transition can't fail"); // Log the transition once - log_state_change(reason); + log_state_change(change_reason); // Remove nmethod from method. unlink_from_method(); diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 7b19cf75a766b..2d5f6a06d35cc 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -469,6 +469,85 @@ class nmethod : public CodeBlob { void oops_do_set_strong_done(nmethod* old_head); public: + enum class ChangeReason : u1 { + C1_codepatch, + C1_deoptimize, + C1_deoptimize_for_patching, + C1_predicate_failed_trap, + CI_replay, + JVMCI_invalidate_nmethod, + JVMCI_invalidate_nmethod_mirror, + JVMCI_materialize_virtual_object, + JVMCI_new_installation, + JVMCI_register_method, + JVMCI_replacing_with_new_code, + JVMCI_reprofile, + marked_for_deoptimization, + missing_exception_handler, + not_used, + OSR_invalidation_back_branch, + OSR_invalidation_for_compiling_with_C1, + OSR_invalidation_of_lower_level, + set_native_function, + uncommon_trap, + whitebox_deoptimization, + zombie, + }; + + + static const char* change_reason_to_string(ChangeReason change_reason) { + switch (change_reason) { + case ChangeReason::C1_codepatch: + return "C1 code patch"; + case ChangeReason::C1_deoptimize: + return "C1 deoptimized"; + case ChangeReason::C1_deoptimize_for_patching: + return "C1 deoptimize for patching"; + case ChangeReason::C1_predicate_failed_trap: + return "C1 predicate failed trap"; + case ChangeReason::CI_replay: + return "CI replay"; + case ChangeReason::JVMCI_invalidate_nmethod: + return "JVMCI invalidate nmethod"; + case ChangeReason::JVMCI_invalidate_nmethod_mirror: + return "JVMCI invalidate nmethod mirror"; + case ChangeReason::JVMCI_materialize_virtual_object: + return "JVMCI materialize virtual object"; + case ChangeReason::JVMCI_new_installation: + return "JVMCI new installation"; + case ChangeReason::JVMCI_register_method: + return "JVMCI register method"; + case ChangeReason::JVMCI_replacing_with_new_code: + return "JVMCI replacing with new code"; + case ChangeReason::JVMCI_reprofile: + return "JVMCI reprofile"; + case ChangeReason::marked_for_deoptimization: + return "marked for deoptimization"; + case ChangeReason::missing_exception_handler: + return "missing exception handler"; + case ChangeReason::not_used: + return "not used"; + case ChangeReason::OSR_invalidation_back_branch: + return "OSR invalidation back branch"; + case ChangeReason::OSR_invalidation_for_compiling_with_C1: + return "OSR invalidation for compiling with C1"; + case ChangeReason::OSR_invalidation_of_lower_level: + return "OSR invalidation of lower level"; + case ChangeReason::set_native_function: + return "set native function"; + case ChangeReason::uncommon_trap: + return "uncommon trap"; + case ChangeReason::whitebox_deoptimization: + return "whitebox deoptimization"; + case ChangeReason::zombie: + return "zombie"; + default: { + assert(false, "Unhandled reason"); + return "Unknown"; + } + } + } + // create nmethod with entry_bci static nmethod* new_nmethod(const methodHandle& method, int compile_id, @@ -631,8 +710,8 @@ class nmethod : public CodeBlob { // alive. It is used when an uncommon trap happens. Returns true // if this thread changed the state of the nmethod or false if // another thread performed the transition. - bool make_not_entrant(const char* reason); - bool make_not_used() { return make_not_entrant("not used"); } + bool make_not_entrant(ChangeReason change_reason); + bool make_not_used() { return make_not_entrant(ChangeReason::not_used); } bool is_marked_for_deoptimization() const { return deoptimization_status() != not_marked; } bool has_been_deoptimized() const { return deoptimization_status() == deoptimize_done; } @@ -945,7 +1024,7 @@ class nmethod : public CodeBlob { // Logging void log_identity(xmlStream* log) const; void log_new_nmethod() const; - void log_state_change(const char* reason) const; + void log_state_change(ChangeReason change_reason) const; // Prints block-level comments, including nmethod specific block labels: void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const; diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index fa18b3c8ab4c0..618082ffaf2de 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -796,7 +796,7 @@ void CompilationPolicy::compile(const methodHandle& mh, int bci, CompLevel level nmethod* osr_nm = mh->lookup_osr_nmethod_for(bci, CompLevel_simple, false); if (osr_nm != nullptr && osr_nm->comp_level() > CompLevel_simple) { // Invalidate the existing OSR nmethod so that a compile at CompLevel_simple is permitted. - osr_nm->make_not_entrant("OSR invalidation for compiling with C1"); + osr_nm->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_for_compiling_with_C1); } compile(mh, bci, CompLevel_simple, THREAD); } @@ -1201,7 +1201,7 @@ void CompilationPolicy::method_back_branch_event(const methodHandle& mh, const m int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci; print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level); } - nm->make_not_entrant("OSR invalidation, back branch"); + nm->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_back_branch); } } // Fix up next_level if necessary to avoid deopts diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index cffac62c1c8b8..bc73fb4939875 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -27,6 +27,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" +#include "code/nmethod.hpp" #include "code/scopeDesc.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compilerEvent.hpp" @@ -1193,7 +1194,7 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject, assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type"); // Clear the link to an old nmethod first JVMCIObject nmethod_mirror = installed_code_handle; - JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, JVMCI_CHECK_0); + JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, nmethod::ChangeReason::JVMCI_replacing_with_new_code, JVMCI_CHECK_0); } else { assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type"); } @@ -1369,7 +1370,7 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) nmethod* code = method->code(); if (code != nullptr) { - code->make_not_entrant("JVMCI reprofile"); + code->make_not_entrant(nmethod::ChangeReason::JVMCI_reprofile); } MethodData* method_data = method->method_data(); @@ -1384,7 +1385,7 @@ C2V_END C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize)) JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod); - JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, JVMCI_CHECK); + JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, nmethod::ChangeReason::JVMCI_invalidate_nmethod, JVMCI_CHECK); C2V_END C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject)) @@ -1809,7 +1810,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_ if (!fst.current()->is_compiled_frame()) { JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected"); } - fst.current()->cb()->as_nmethod()->make_not_entrant("JVMCI materialize virtual objects"); + fst.current()->cb()->as_nmethod()->make_not_entrant(nmethod::ChangeReason::JVMCI_materialize_virtual_object); } Deoptimization::deoptimize(thread, *fst.current(), Deoptimization::Reason_none); // look for the frame again as it has been updated by deopt (pc, deopt state...) diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index a23b09c3c1e70..d9502cf859f3b 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1752,7 +1752,7 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c } -void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JVMCI_TRAPS) { +void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::ChangeReason change_reason, JVMCI_TRAPS) { if (mirror.is_null()) { JVMCI_THROW(NullPointerException); } @@ -1775,7 +1775,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JV if (!deoptimize) { // Prevent future executions of the nmethod but let current executions complete. - nm->make_not_entrant("JVMCI invalidate nmethod mirror"); + nm->make_not_entrant(change_reason); // Do not clear the address field here as the Java code may still // want to later call this method with deoptimize == true. That requires @@ -1784,7 +1784,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JV // Deoptimize the nmethod immediately. DeoptimizationScope deopt_scope; deopt_scope.mark(nm); - nm->make_not_entrant("JVMCI invalidate nmethod mirror"); + nm->make_not_entrant(change_reason); nm->make_deoptimized(); deopt_scope.deoptimize_marked(); diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index 69f6647b0d618..b7b7c8f677174 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -462,7 +462,7 @@ class JVMCIEnv : public ResourceObj { // field of `mirror` to prevent it from being called. // If `deoptimize` is true, the nmethod is immediately deoptimized. // The HotSpotNmethod.address field is zero upon returning. - void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, JVMCI_TRAPS); + void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, nmethod::ChangeReason change_reason, JVMCI_TRAPS); void initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 8e885e5f7f9bf..66359d854a0f2 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -2196,7 +2196,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, tty->print_cr("Replacing method %s", method_name); } if (old != nullptr) { - old->make_not_entrant("JVMCI register method"); + old->make_not_entrant(nmethod::ChangeReason::JVMCI_register_method); } LogTarget(Info, nmethod, install) lt; diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 715c8f473d087..c96d9f5b5bd45 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -3494,7 +3494,7 @@ void InstanceKlass::add_osr_nmethod(nmethod* n) { for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) { nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true); if (inv != nullptr && inv->is_in_use()) { - inv->make_not_entrant("OSR invalidation of lower levels"); + inv->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_of_lower_level); } } } diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 0c4430b44c3f5..4fc9cb51f25e2 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -970,7 +970,7 @@ void Method::set_native_function(address function, bool post_event_flag) { // If so, we have to make it not_entrant. nmethod* nm = code(); // Put it into local variable to guard against concurrent updates if (nm != nullptr) { - nm->make_not_entrant("set native function"); + nm->make_not_entrant(nmethod::ChangeReason::set_native_function); } } diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index e08a5ba5ebd12..3fb43eea0fa3f 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -794,7 +794,7 @@ class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation { if (_make_not_entrant) { nmethod* nm = CodeCache::find_nmethod(f->pc()); assert(nm != nullptr, "did not find nmethod"); - nm->make_not_entrant("Whitebox deoptimization"); + nm->make_not_entrant(nmethod::ChangeReason::whitebox_deoptimization); } ++_result; } diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 5e4aaf31a3be8..78ee8e70fa15e 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1813,7 +1813,7 @@ void Deoptimization::deoptimize(JavaThread* thread, frame fr, DeoptReason reason #if INCLUDE_JVMCI address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm) { // there is no exception handler for this pc => deoptimize - nm->make_not_entrant("missing exception handler"); + nm->make_not_entrant(nmethod::ChangeReason::missing_exception_handler); // Use Deoptimization::deoptimize for all of its side-effects: // gathering traps statistics, logging... @@ -2442,7 +2442,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr // Recompile if (make_not_entrant) { - if (!nm->make_not_entrant("uncommon trap")) { + if (!nm->make_not_entrant(nmethod::ChangeReason::uncommon_trap)) { return; // the call did not change nmethod's state } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index b5c7709ac88f1..18a370e2c04c2 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -1339,7 +1339,7 @@ void JavaThread::make_zombies() { // it is a Java nmethod nmethod* nm = CodeCache::find_nmethod(fst.current()->pc()); assert(nm != nullptr, "did not find nmethod"); - nm->make_not_entrant("zombie"); + nm->make_not_entrant(nmethod::ChangeReason::zombie); } } }