Skip to content
4 changes: 2 additions & 2 deletions src/hotspot/share/code/nmethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2084,7 +2084,7 @@ bool nmethod::make_not_entrant(ChangeReason change_reason) {
// Invalidate can't occur while holding the NMethodState_lock
JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
if (nmethod_data != nullptr) {
nmethod_data->invalidate_nmethod_mirror(this);
nmethod_data->invalidate_nmethod_mirror(this, change_reason);
}
#endif

Expand Down Expand Up @@ -2122,7 +2122,7 @@ void nmethod::unlink() {
// Clear the link between this nmethod and a HotSpotNmethod mirror
JVMCINMethodData* nmethod_data = jvmci_nmethod_data();
if (nmethod_data != nullptr) {
nmethod_data->invalidate_nmethod_mirror(this);
nmethod_data->invalidate_nmethod_mirror(this, is_cold() ? nmethod::ChangeReason::GC_unlinking_cold : nmethod::ChangeReason::GC_unlinking);
}
#endif

Expand Down
20 changes: 8 additions & 12 deletions src/hotspot/share/code/nmethod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,18 +471,20 @@ class nmethod : public CodeBlob {
void oops_do_set_strong_done(nmethod* old_head);

public:
// If you change anything in this enum please patch
// vmStructs_jvmci.cpp accordingly.
enum class ChangeReason : u1 {
unknown,
C1_codepatch,
C1_deoptimize,
C1_deoptimize_for_patching,
C1_predicate_failed_trap,
CI_replay,
GC_unlinking,
GC_unlinking_cold,
JVMCI_invalidate_nmethod,
JVMCI_invalidate_nmethod_mirror,
JVMCI_materialize_virtual_object,
JVMCI_new_installation,
JVMCI_register_method,
JVMCI_replacing_with_new_code,
JVMCI_replaced_with_new_code,
JVMCI_reprofile,
marked_for_deoptimization,
missing_exception_handler,
Expand Down Expand Up @@ -511,16 +513,10 @@ class nmethod : public CodeBlob {
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_replaced_with_new_code:
return "JVMCI replaced with new code";
case ChangeReason::JVMCI_reprofile:
return "JVMCI reprofile";
case ChangeReason::marked_for_deoptimization:
Expand Down
17 changes: 13 additions & 4 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,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, nmethod::ChangeReason::JVMCI_replacing_with_new_code, JVMCI_CHECK_0);
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, nmethod::ChangeReason::JVMCI_replaced_with_new_code, JVMCI_CHECK_0);
} else {
assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type");
}
Expand All @@ -1218,6 +1218,14 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject,
return result;
C2V_END

C2V_VMENTRY_0(jobject, getInvalidationReasonString, (JNIEnv *env, jobject, jint invalidation_reason))
HandleMark hm(THREAD);
JNIHandleMark jni_hm(thread);
nmethod::ChangeReason reason = static_cast<nmethod::ChangeReason>(invalidation_reason);
JVMCIObject desc = JVMCIENV->create_string(nmethod::change_reason_to_string(reason), JVMCI_CHECK_NULL);
return JVMCIENV->get_jobject(desc);
C2V_END

C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv* env, jobject))
JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK);
CompilerStatistics* stats = compiler->stats();
Expand Down Expand Up @@ -1396,9 +1404,9 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
C2V_END


C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize))
C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize, jint change_reason))
JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, nmethod::ChangeReason::JVMCI_invalidate_nmethod, JVMCI_CHECK);
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, static_cast<nmethod::ChangeReason>(change_reason), JVMCI_CHECK);
C2V_END

C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject))
Expand Down Expand Up @@ -3352,6 +3360,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZ)" HS_KLASS, FN_PTR(getResolvedJavaType0)},
{CC "readConfiguration", CC "()[" OBJECT, FN_PTR(readConfiguration)},
{CC "installCode0", CC "(JJZ" HS_COMPILED_CODE "[" OBJECT INSTALLED_CODE "J[B)I", FN_PTR(installCode0)},
{CC "getInvalidationReasonString", CC "(I)" STRING, FN_PTR(getInvalidationReasonString)},
{CC "getInstallCodeFlags", CC "()I", FN_PTR(getInstallCodeFlags)},
{CC "resetCompilationStatistics", CC "()V", FN_PTR(resetCompilationStatistics)},
{CC "disassembleCodeBlob", CC "(" INSTALLED_CODE ")" STRING, FN_PTR(disassembleCodeBlob)},
Expand All @@ -3360,7 +3369,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getLocalVariableTableStart", CC "(" HS_METHOD2 ")J", FN_PTR(getLocalVariableTableStart)},
{CC "getLocalVariableTableLength", CC "(" HS_METHOD2 ")I", FN_PTR(getLocalVariableTableLength)},
{CC "reprofile", CC "(" HS_METHOD2 ")V", FN_PTR(reprofile)},
{CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "Z)V", FN_PTR(invalidateHotSpotNmethod)},
{CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "ZI)V", FN_PTR(invalidateHotSpotNmethod)},
{CC "collectCounters", CC "()[J", FN_PTR(collectCounters)},
{CC "getCountersSize", CC "()I", FN_PTR(getCountersSize)},
{CC "setCountersSize", CC "(I)Z", FN_PTR(setCountersSize)},
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/jvmci/jvmciEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,7 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c
set_InstalledCode_entryPoint(installed_code, (jlong) cb->code_begin());
}
set_InstalledCode_address(installed_code, (jlong) cb);
set_HotSpotNmethod_invalidationReason(installed_code, static_cast<int>(nmethod::ChangeReason::unknown));
set_HotSpotInstalledCode_size(installed_code, cb->size());
set_HotSpotInstalledCode_codeStart(installed_code, (jlong) cb->code_begin());
set_HotSpotInstalledCode_codeSize(installed_code, cb->code_size());
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/jvmci/jvmciJavaClasses.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
boolean_field(HotSpotNmethod, isDefault) \
long_field(HotSpotNmethod, compileIdSnapshot) \
object_field(HotSpotNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;") \
int_field(HotSpotNmethod, invalidationReason) \
jvmci_constructor(HotSpotNmethod, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
end_class \
start_class(HotSpotCompiledCode, jdk_vm_ci_hotspot_HotSpotCompiledCode) \
Expand Down
6 changes: 4 additions & 2 deletions src/hotspot/share/jvmci/jvmciRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) {
Universe::heap()->register_nmethod(nm);
}

void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm, nmethod::ChangeReason change_reason) {
oop nmethod_mirror = get_nmethod_mirror(nm);
if (nmethod_mirror == nullptr) {
return;
Expand All @@ -815,12 +815,14 @@ void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
// an InvalidInstalledCodeException.
HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast<int>(change_reason));
HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0);
} else if (nm->is_not_entrant()) {
// Zero the entry point so any new invocation will fail but keep
// the address link around that so that existing activations can
// be deoptimized via the mirror (i.e. JVMCIEnv::invalidate_installed_code).
HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast<int>(change_reason));
HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0);
}
}
Expand Down Expand Up @@ -2184,7 +2186,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
tty->print_cr("Replacing method %s", method_name);
}
if (old != nullptr) {
old->make_not_entrant(nmethod::ChangeReason::JVMCI_register_method);
old->make_not_entrant(nmethod::ChangeReason::JVMCI_replaced_with_new_code);
}

LogTarget(Info, nmethod, install) lt;
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmciRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class JVMCINMethodData : public ResourceObj {

// Clears the HotSpotNmethod.address field in the mirror. If nm
// is dead, the HotSpotNmethod.entryPoint field is also cleared.
void invalidate_nmethod_mirror(nmethod* nm);
void invalidate_nmethod_mirror(nmethod* nm, nmethod::ChangeReason change_reason);

// Gets the mirror from nm's oops table.
oop get_nmethod_mirror(nmethod* nm);
Expand Down
25 changes: 24 additions & 1 deletion src/hotspot/share/jvmci/vmStructs_jvmci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,30 @@
declare_constant_with_value("LockStack::_end_offset", LockStack::end_offset()) \
declare_constant_with_value("OMCache::oop_to_oop_difference", OMCache::oop_to_oop_difference()) \
declare_constant_with_value("OMCache::oop_to_monitor_difference", OMCache::oop_to_monitor_difference()) \
\
\
declare_constant_with_value("nmethod::ChangeReason::UNKNOWN", nmethod::ChangeReason::unknown) \
declare_constant_with_value("nmethod::ChangeReason::C1_CODEPATCH", nmethod::ChangeReason::C1_codepatch) \
declare_constant_with_value("nmethod::ChangeReason::C1_DEOPTIMIZE", nmethod::ChangeReason::C1_deoptimize) \
declare_constant_with_value("nmethod::ChangeReason::C1_DEOPTIMIZE_FOR_PATCHING", nmethod::ChangeReason::C1_deoptimize_for_patching) \
declare_constant_with_value("nmethod::ChangeReason::C1_PREDICATE_FAILED_TRAP", nmethod::ChangeReason::C1_predicate_failed_trap) \
declare_constant_with_value("nmethod::ChangeReason::CI_REPLAY", nmethod::ChangeReason::CI_replay) \
declare_constant_with_value("nmethod::ChangeReason::GC_UNLINKING", nmethod::ChangeReason::GC_unlinking) \
declare_constant_with_value("nmethod::ChangeReason::GC_UNLINKING_COLD", nmethod::ChangeReason::GC_unlinking_cold) \
declare_constant_with_value("nmethod::ChangeReason::JVMCI_INVALIDATE_NMETHOD", nmethod::ChangeReason::JVMCI_invalidate_nmethod) \
declare_constant_with_value("nmethod::ChangeReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT", nmethod::ChangeReason::JVMCI_materialize_virtual_object) \
declare_constant_with_value("nmethod::ChangeReason::JVMCI_REPLACED_WITH_NEW_CODE", nmethod::ChangeReason::JVMCI_replaced_with_new_code) \
declare_constant_with_value("nmethod::ChangeReason::JVMCI_REPROFILE", nmethod::ChangeReason::JVMCI_reprofile) \
declare_constant_with_value("nmethod::ChangeReason::MARKED_FOR_DEOPTIMIZATION", nmethod::ChangeReason::marked_for_deoptimization) \
declare_constant_with_value("nmethod::ChangeReason::MISSING_EXCEPTION_HANDLER", nmethod::ChangeReason::missing_exception_handler) \
declare_constant_with_value("nmethod::ChangeReason::NOT_USED", nmethod::ChangeReason::not_used) \
declare_constant_with_value("nmethod::ChangeReason::OSR_INVALIDATION_BACK_BRANCH", nmethod::ChangeReason::OSR_invalidation_back_branch) \
declare_constant_with_value("nmethod::ChangeReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1", nmethod::ChangeReason::OSR_invalidation_for_compiling_with_C1) \
declare_constant_with_value("nmethod::ChangeReason::OSR_INVALIDATION_OF_LOWER_LEVEL", nmethod::ChangeReason::OSR_invalidation_of_lower_level) \
declare_constant_with_value("nmethod::ChangeReason::SET_NATIVE_FUNCTION", nmethod::ChangeReason::set_native_function) \
declare_constant_with_value("nmethod::ChangeReason::UNCOMMON_TRAP", nmethod::ChangeReason::uncommon_trap) \
declare_constant_with_value("nmethod::ChangeReason::WHITEBOX_DEOPTIMIZATION", nmethod::ChangeReason::whitebox_deoptimization) \
declare_constant_with_value("nmethod::ChangeReason::ZOMBIE", nmethod::ChangeReason::zombie) \
\
declare_constant(CodeInstaller::VERIFIED_ENTRY) \
declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \
declare_constant(CodeInstaller::OSR_ENTRY) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public byte[] getCode() {
}

/**
* Equivalent to calling {@link #invalidate(boolean)} with a {@code true} argument.
* Equivalent to calling {@link #invalidate(boolean, int)} with {@code true} and {@code 0} as arguments.
*/
public void invalidate() {
invalidate(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,8 @@ native int installCode0(long compiledCodeBuffer,
long failedSpeculationsAddress,
byte[] speculations);

native String getInvalidationReasonString(int invalidationReason);

/**
* Gets flags specifying optional parts of code info. Only if a flag is set, will the
* corresponding code info being included in the {@linkplain HotSpotCompiledCodeStream
Expand Down Expand Up @@ -842,7 +844,7 @@ void reprofile(HotSpotResolvedJavaMethodImpl method) {
* {@code nmethod} associated with {@code nmethodMirror} is also made non-entrant and if
* {@code deoptimize == true} any current activations of the {@code nmethod} are deoptimized.
*/
native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize);
native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize, int invalidationReason);

/**
* Collects the current values of all JVMCI benchmark counters, summed up over all threads.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,20 @@ public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compile
return logOrDump(resultInstalledCode, compiledCode);
}

@Override
public void invalidateInstalledCode(InstalledCode installedCode) {
public void invalidateInstalledCode(InstalledCode installedCode, int invalidationReason) {
if (installedCode instanceof HotSpotNmethod) {
HotSpotNmethod nmethod = (HotSpotNmethod) installedCode;
nmethod.invalidate(true);
nmethod.invalidate(true, invalidationReason);
} else {
throw new IllegalArgumentException("Cannot invalidate a " + Objects.requireNonNull(installedCode).getClass().getName());
}
}

@Override
public void invalidateInstalledCode(InstalledCode installedCode) {
invalidateInstalledCode(installedCode, unknownInvalidationReason());
}

@Override
public TargetDescription getTarget() {
return target;
Expand Down Expand Up @@ -201,4 +205,8 @@ public int interpreterFrameSize(BytecodeFrame pos) {
public void resetCompilationStatistics() {
runtime.getCompilerToVM().resetCompilationStatistics();
}

private static int unknownInvalidationReason() {
return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::ChangeReason::Unknown", Integer.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import jdk.vm.ci.code.InstalledCode;
import jdk.vm.ci.code.InvalidInstalledCodeException;
import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.ResolvedJavaMethod;
Expand Down Expand Up @@ -76,12 +77,18 @@ boolean inOopsTable() {
*/
private final long compileIdSnapshot;

/**
* Identify the reason that caused this nmethod to be invalidated.
*/
private int invalidationReason;

HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, long compileId) {
super(name);
this.method = method;
this.isDefault = isDefault;
boolean inOopsTable = !IS_IN_NATIVE_IMAGE && !isDefault;
this.compileIdSnapshot = inOopsTable ? 0L : compileId;
this.invalidationReason = 0;
assert inOopsTable || compileId != 0L : this;
}

Expand Down Expand Up @@ -122,9 +129,13 @@ public ResolvedJavaMethod getMethod() {
return method;
}

public void invalidate(boolean deoptimize, int invalidationReason) {
compilerToVM().invalidateHotSpotNmethod(this, deoptimize, invalidationReason);
}

@Override
public void invalidate(boolean deoptimize) {
compilerToVM().invalidateHotSpotNmethod(this, deoptimize);
invalidate(deoptimize, unknownInvalidationReason());
}

@Override
Expand Down Expand Up @@ -188,4 +199,22 @@ public Object executeVarargs(Object... args) throws InvalidInstalledCodeExceptio
public long getStart() {
return isValid() ? super.getStart() : 0;
}

/**
* @return an integer representing the reason why this nmethod was invalidated.
*/
public int getInvalidationReason() {
return invalidationReason;
}

/**
* @return a String describing the reason why this nmethod was invalidated.
*/
public String getInvalidationReasonString() {
return compilerToVM().getInvalidationReasonString(this.getInvalidationReason());
}

private static int unknownInvalidationReason() {
return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::ChangeReason::Unknown", Integer.class);
}
}
Loading