Refactoring: move changes to HotSpotNmethod class; remove enum on Java side; rename field to invalidationReason

This commit is contained in:
JohnTortugo 2025-06-12 00:25:12 +00:00
parent 5e4b814540
commit fcf838bd3e
15 changed files with 63 additions and 109 deletions

View File

@ -472,7 +472,7 @@ class nmethod : public CodeBlob {
public:
// If you change anything in this enum please patch
// vmStructs_jvmci.cpp and HotSpotNmethod.java accordingly.
// vmStructs_jvmci.cpp accordingly.
enum class ChangeReason : u1 {
unknown,
C1_codepatch,
@ -483,11 +483,8 @@ public:
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,
@ -516,16 +513,10 @@ public:
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:

View File

@ -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");
}
@ -1218,10 +1218,10 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject,
return result;
C2V_END
C2V_VMENTRY_0(jobject, getChangeReasonDescription, (JNIEnv *env, jobject, jint change_reason))
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>(change_reason);
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
@ -3360,7 +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 "getChangeReasonDescription", CC "(I)" STRING, FN_PTR(getChangeReasonDescription)},
{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)},

View File

@ -1744,7 +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_InstalledCode_changeReason(installed_code, static_cast<int>(nmethod::ChangeReason::JVMCI_new_installation));
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());

View File

@ -92,7 +92,6 @@
long_field(InstalledCode, entryPoint) \
long_field(InstalledCode, version) \
object_field(InstalledCode, name, "Ljava/lang/String;") \
int_field(InstalledCode, changeReason) \
end_class \
start_class(HotSpotInstalledCode, jdk_vm_ci_hotspot_HotSpotInstalledCode) \
int_field(HotSpotInstalledCode, size) \
@ -103,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) \

View File

@ -815,14 +815,14 @@ void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm, nmethod::ChangeRea
// an InvalidInstalledCodeException.
HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
HotSpotJVMCI::InstalledCode::set_changeReason(jvmciEnv, nmethod_mirror, static_cast<int>(change_reason));
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::InstalledCode::set_changeReason(jvmciEnv, nmethod_mirror, static_cast<int>(change_reason));
HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast<int>(change_reason));
HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0);
}
}
@ -2186,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;

View File

@ -574,11 +574,8 @@
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_INVALIDATE_NMETHOD_MIRROR", nmethod::ChangeReason::JVMCI_invalidate_nmethod_mirror) \
declare_constant_with_value("nmethod::ChangeReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT", nmethod::ChangeReason::JVMCI_materialize_virtual_object) \
declare_constant_with_value("nmethod::ChangeReason::JVMCI_NEW_INSTALLATION", nmethod::ChangeReason::JVMCI_new_installation) \
declare_constant_with_value("nmethod::ChangeReason::JVMCI_REGISTER_METHOD", nmethod::ChangeReason::JVMCI_register_method) \
declare_constant_with_value("nmethod::ChangeReason::JVMCI_REPLACING_WITH_NEW_CODE", nmethod::ChangeReason::JVMCI_replacing_with_new_code) \
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) \

View File

@ -91,7 +91,7 @@ public interface CodeCacheProvider {
* raised the next time {@code installedCode} is
* {@linkplain InstalledCode#executeVarargs(Object...) executed}.
*/
void invalidateInstalledCode(InstalledCode installedCode, int changeReason);
void invalidateInstalledCode(InstalledCode installedCode);
/**
* Gets a name for a {@link Mark} mark.

View File

@ -46,11 +46,6 @@ public class InstalledCode {
protected final String name;
/**
* Identify the reason that caused this installed code to change.
*/
protected int changeReason;
/**
* The maximum length of an InstalledCode name. This name is typically installed into
* the code cache so it should have a reasonable limit.
@ -124,20 +119,6 @@ public class InstalledCode {
return address != 0;
}
/**
* @return an integer representing the reason why this InstalledCode changed.
*/
public int getChangeReason() {
return changeReason;
}
/**
* @return a String describing the reason why this InstalledCode changed.
*/
public String getChangeReasonDescription() {
return null;
}
/**
* Returns a copy of this installed code if it is {@linkplain #isValid() valid}, null otherwise.
*/
@ -149,7 +130,7 @@ public class InstalledCode {
* Equivalent to calling {@link #invalidate(boolean, int)} with {@code true} and {@code 0} as arguments.
*/
public void invalidate() {
invalidate(true, 0);
invalidate(true);
}
/**
@ -165,9 +146,8 @@ public class InstalledCode {
* If {@code false}, any existing invocation will continue until it completes or
* there is a subsequent call to this method with {@code deoptimize == true} before
* the invocation completes.
* @param changeReason an integer code representing the reason why this InstalledCode is being marked as invalidated.
*/
public void invalidate(boolean deoptimize, int statusReason) {
public void invalidate(boolean deoptimize) {
throw new UnsupportedOperationException();
}

View File

@ -654,7 +654,7 @@ final class CompilerToVM {
long failedSpeculationsAddress,
byte[] speculations);
native String getChangeReasonDescription(int changeReason);
native String getInvalidationReasonString(int invalidationReason);
/**
* Gets flags specifying optional parts of code info. Only if a flag is set, will the
@ -844,7 +844,7 @@ final class CompilerToVM {
* {@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, int changeReason);
native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize, int invalidationReason);
/**
* Collects the current values of all JVMCI benchmark counters, summed up over all threads.

View File

@ -154,16 +154,20 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider {
return logOrDump(resultInstalledCode, compiledCode);
}
@Override
public void invalidateInstalledCode(InstalledCode installedCode, int changeReason) {
public void invalidateInstalledCode(InstalledCode installedCode, int invalidationReason) {
if (installedCode instanceof HotSpotNmethod) {
HotSpotNmethod nmethod = (HotSpotNmethod) installedCode;
nmethod.invalidate(true, changeReason);
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;
@ -201,4 +205,8 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider {
public void resetCompilationStatistics() {
runtime.getCompilerToVM().resetCompilationStatistics();
}
private static int unknownInvalidationReason() {
return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::ChangeReason::Unknown", Integer.class);
}
}

View File

@ -82,9 +82,4 @@ public abstract class HotSpotInstalledCode extends InstalledCode {
public byte[] getCode() {
return compilerToVM().getCode(this);
}
@Override
public String getChangeReasonDescription() {
return compilerToVM().getChangeReasonDescription(this.getChangeReason());
}
}

View File

@ -78,45 +78,9 @@ public class HotSpotNmethod extends HotSpotInstalledCode {
private final long compileIdSnapshot;
/**
* This is a mirror of the ChangeReason enum defined in nmethod.hpp.
* It defines constants representing different reasons why an nmethod
* changed or was invalidated.
* Identify the reason that caused this nmethod to be invalidated.
*/
public enum ChangeReason {
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_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;
ChangeReason() {
int expect = ordinal();
int actual = nmethodChangeReasonValue(name());
if (expect != actual) {
throw new JVMCIError("%s: expected %d, got %d", name(), expect, actual);
}
}
}
private int invalidationReason;
HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, long compileId) {
super(name);
@ -124,6 +88,7 @@ public class HotSpotNmethod extends HotSpotInstalledCode {
this.isDefault = isDefault;
boolean inOopsTable = !IS_IN_NATIVE_IMAGE && !isDefault;
this.compileIdSnapshot = inOopsTable ? 0L : compileId;
this.invalidationReason = 0;
assert inOopsTable || compileId != 0L : this;
}
@ -164,9 +129,13 @@ public class HotSpotNmethod extends HotSpotInstalledCode {
return method;
}
public void invalidate(boolean deoptimize, int invalidationReason) {
compilerToVM().invalidateHotSpotNmethod(this, deoptimize, invalidationReason);
}
@Override
public void invalidate(boolean deoptimize, int changeReason) {
compilerToVM().invalidateHotSpotNmethod(this, deoptimize, changeReason);
public void invalidate(boolean deoptimize) {
invalidate(deoptimize, unknownInvalidationReason());
}
@Override
@ -231,7 +200,21 @@ public class HotSpotNmethod extends HotSpotInstalledCode {
return isValid() ? super.getStart() : 0;
}
private static int nmethodChangeReasonValue(String name) {
return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::ChangeReason::" + name, Integer.class);
/**
* @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);
}
}

View File

@ -49,7 +49,7 @@ import org.junit.Test;
import java.lang.reflect.Method;
/**
* Test if passing InstalledCode changeReason around works.
* Test if setting HotSpotNmethod invalidation reason around works.
*/
public class CodeInvalidationReasonTest extends CodeInstallationTest {
@ -69,9 +69,9 @@ public class CodeInvalidationReasonTest extends CodeInstallationTest {
Method method = getMethod("add", int.class, int.class);
HotSpotNmethod nmethod = test(CodeInvalidationReasonTest::compileAdd, method, 5, 7);
Asserts.assertEquals(config.JVMCI_new_installation, nmethod.getChangeReason());
Asserts.assertEquals(config.NMETHOD_CHANGE_REASON_UNKNOWN, nmethod.getInvalidationReason());
nmethod.invalidate(true, config.JVMCI_invalidate_nmethod);
Asserts.assertEquals(config.JVMCI_invalidate_nmethod, nmethod.getChangeReason());
nmethod.invalidate(true, config.NMETHOD_CHANGE_REASON_JVMCI_INVALIDATE);
Asserts.assertEquals(config.NMETHOD_CHANGE_REASON_JVMCI_INVALIDATE, nmethod.getInvalidationReason());
}
}

View File

@ -71,13 +71,13 @@ public class SimpleCodeInstallationTest extends CodeInstallationTest {
Asserts.assertNotEquals(nmethod.getStart(), 0L);
// Make nmethod non-entrant but still alive
nmethod.invalidate(false, config.JVMCI_invalidate_nmethod);
nmethod.invalidate(false, config.NMETHOD_CHANGE_REASON_JVMCI_INVALIDATE);
Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod);
Asserts.assertTrue(nmethod.isAlive(), "code is not alive, i = " + nmethod);
Asserts.assertEquals(nmethod.getStart(), 0L);
// Deoptimize the nmethod and cut the link to it from the HotSpotNmethod
nmethod.invalidate(true, config.JVMCI_invalidate_nmethod);
nmethod.invalidate(true, config.NMETHOD_CHANGE_REASON_JVMCI_INVALIDATE);
Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod);
Asserts.assertFalse(nmethod.isAlive(), "code is alive, i = " + nmethod);
Asserts.assertEquals(nmethod.getStart(), 0L);

View File

@ -55,8 +55,8 @@ public class TestHotSpotVMConfig extends HotSpotVMConfigAccess {
public final int maxOopMapStackOffset = getFieldValue("CompilerToVM::Data::_max_oop_map_stack_offset", Integer.class, "int");
public final int heapWordSize = getConstant("HeapWordSize", Integer.class);
public final int JVMCI_new_installation = getConstant("nmethod::ChangeReason::JVMCI_NEW_INSTALLATION", Integer.class);
public final int JVMCI_invalidate_nmethod = getConstant("nmethod::ChangeReason::JVMCI_INVALIDATE_NMETHOD", Integer.class);
public final int NMETHOD_CHANGE_REASON_UNKNOWN = getConstant("nmethod::ChangeReason::UNKNOWN", Integer.class);
public final int NMETHOD_CHANGE_REASON_JVMCI_INVALIDATE = getConstant("nmethod::ChangeReason::JVMCI_INVALIDATE_NMETHOD", Integer.class);
public final boolean ropProtection;