8292917: [JVMCI] Extend InstalledCode API to make an nmethod non entrant.

Reviewed-by: never
This commit is contained in:
Doug Simon 2022-08-27 08:21:58 +00:00
parent 1500d3dfb2
commit b0e0b87891
8 changed files with 52 additions and 27 deletions
src
hotspot/share/jvmci
jdk.internal.vm.ci/share/classes
jdk.vm.ci.code/src/jdk/vm/ci/code
jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot
test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot

@ -975,7 +975,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, JVMCI_CHECK_0);
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, JVMCI_CHECK_0);
} else {
assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type");
}
@ -1145,9 +1145,9 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
C2V_END
C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod))
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, JVMCI_CHECK);
JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, JVMCI_CHECK);
C2V_END
C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject))
@ -2862,7 +2862,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 ")V", FN_PTR(invalidateHotSpotNmethod)},
{CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "Z)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)},

@ -1510,7 +1510,7 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c
}
void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, JVMCI_TRAPS) {
void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JVMCI_TRAPS) {
if (mirror.is_null()) {
JVMCI_THROW(NullPointerException);
}
@ -1529,8 +1529,13 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, JVMCI_TRAPS) {
"Cannot invalidate HotSpotNmethod object in shared library VM heap from non-JavaThread");
}
// Invalidating the HotSpotNmethod means we want the nmethod to be deoptimized.
Deoptimization::deoptimize_all_marked(nm);
if (!deoptimize) {
// Prevent future executions of the nmethod but let current executions complete.
nm->make_not_entrant();
} else {
// We want the nmethod to be deoptimized immediately.
Deoptimization::deoptimize_all_marked(nm);
}
// A HotSpotNmethod instance can only reference a single nmethod
// during its lifetime so simply clear it here.

@ -412,9 +412,11 @@ public:
// Destroys a JNI global handle created by JVMCIEnv::make_global.
void destroy_global(JVMCIObject object);
// Deoptimizes the nmethod (if any) in the HotSpotNmethod.address
// field of mirror. The field is subsequently zeroed.
void invalidate_nmethod_mirror(JVMCIObject mirror, JVMCI_TRAPS);
// Updates the nmethod (if any) in the HotSpotNmethod.address
// 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 initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS);

@ -29,12 +29,13 @@ package jdk.vm.ci.code;
public class InstalledCode {
/**
* Raw address address of entity representing this installed code.
* Address of the entity (e.g., HotSpot {@code nmethod} or {@code RuntimeStub}) representing
* this installed code.
*/
protected long address;
/**
* Raw address of entryPoint of this installed code.
* Address of the entryPoint of this installed code.
*/
protected long entryPoint;
@ -50,7 +51,8 @@ public class InstalledCode {
}
/**
* @return the address of entity representing this installed code.
* @return the address of entity (e.g., HotSpot {@code nmethod} or {@code RuntimeStub})
* representing this installed code
*/
public long getAddress() {
return address;
@ -94,8 +96,7 @@ public class InstalledCode {
}
/**
* @return true if the code represented by this object still exists and might have live
* activations, false otherwise (may happen due to deopt, etc.)
* @return true if this object still points to installed code
*/
public boolean isAlive() {
return address != 0;
@ -109,11 +110,27 @@ public class InstalledCode {
}
/**
* Invalidates this installed code such that any subsequent
* {@linkplain #executeVarargs(Object...) invocation} will throw an
* {@link InvalidInstalledCodeException} and all existing invocations will be deoptimized.
* Equivalent to calling {@link #invalidate(boolean)} with a {@code true} argument.
*/
public void invalidate() {
invalidate(true);
}
/**
* Invalidates this installed code such that any subsequent
* {@linkplain #executeVarargs(Object...) invocation} will throw an
* {@link InvalidInstalledCodeException}.
*
* If this installed code is already {@linkplain #isValid() invalid}, this method has no effect.
* A subsequent call to {@link #isAlive()} or {@link #isValid()} on this object will return
* {@code false}.
*
* @param deoptimize if {@code true}, all existing invocations will be immediately deoptimized.
* 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.
*/
public void invalidate(boolean deoptimize) {
throw new UnsupportedOperationException();
}

@ -715,12 +715,12 @@ final class CompilerToVM {
private native void reprofile(HotSpotResolvedJavaMethodImpl method, long methodPointer);
/**
* Invalidates {@code nmethodMirror} such that {@link InvalidInstalledCodeException} will be
* raised the next time {@code nmethodMirror} is {@linkplain #executeHotSpotNmethod executed}.
* The {@code nmethod} associated with {@code nmethodMirror} is also made non-entrant and any
* current activations of the {@code nmethod} are deoptimized.
* Updates {@code nmethodMirror} such that {@link InvalidInstalledCodeException} will be raised
* the next time {@code nmethodMirror} is {@linkplain #executeHotSpotNmethod executed}. The
* {@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);
native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize);
/**
* Collects the current values of all JVMCI benchmark counters, summed up over all threads.

@ -157,7 +157,8 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider {
@Override
public void invalidateInstalledCode(InstalledCode installedCode) {
if (installedCode instanceof HotSpotNmethod) {
runtime.getCompilerToVM().invalidateHotSpotNmethod((HotSpotNmethod) installedCode);
HotSpotNmethod nmethod = (HotSpotNmethod) installedCode;
nmethod.invalidate(true);
} else {
throw new IllegalArgumentException("Cannot invalidate a " + Objects.requireNonNull(installedCode).getClass().getName());
}

@ -123,8 +123,8 @@ public class HotSpotNmethod extends HotSpotInstalledCode {
}
@Override
public void invalidate() {
compilerToVM().invalidateHotSpotNmethod(this);
public void invalidate(boolean deoptimize) {
compilerToVM().invalidateHotSpotNmethod(this, deoptimize);
}
@Override

@ -244,7 +244,7 @@ public class CompilerToVMHelper {
}
public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror) {
CTVM.invalidateHotSpotNmethod(nmethodMirror);
CTVM.invalidateHotSpotNmethod(nmethodMirror, true);
}
public static long[] collectCounters() {