Skip to content

Commit

Permalink
8304303: implement VirtualThread class notifyJvmti methods as C2 intr…
Browse files Browse the repository at this point in the history
…insics

Reviewed-by: vlivanov, lmesnik
  • Loading branch information
Serguei Spitsyn committed Mar 20, 2023
1 parent 917f936 commit b0fd761
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 56 deletions.
6 changes: 2 additions & 4 deletions make/data/hotspot-symbols/symbols-unix
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,8 @@ JVM_DefineModule
JVM_SetBootLoaderUnnamedModule

# Virtual thread notifications for JVMTI
JVM_VirtualThreadMountBegin
JVM_VirtualThreadMountEnd
JVM_VirtualThreadUnmountBegin
JVM_VirtualThreadUnmountEnd
JVM_VirtualThreadMount
JVM_VirtualThreadUnmount
JVM_VirtualThreadHideFrames

# Scoped values
Expand Down
10 changes: 2 additions & 8 deletions src/hotspot/share/include/jvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1144,16 +1144,10 @@ JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass);
* Virtual thread support.
*/
JNIEXPORT void JNICALL
JVM_VirtualThreadMountBegin(JNIEnv* env, jobject vthread, jboolean first_mount);
JVM_VirtualThreadMount(JNIEnv* env, jobject vthread, jboolean hide, jboolean first_mount);

JNIEXPORT void JNICALL
JVM_VirtualThreadMountEnd(JNIEnv* env, jobject vthread, jboolean first_mount);

JNIEXPORT void JNICALL
JVM_VirtualThreadUnmountBegin(JNIEnv* env, jobject vthread, jboolean last_unmount);

JNIEXPORT void JNICALL
JVM_VirtualThreadUnmountEnd(JNIEnv* env, jobject vthread, jboolean last_unmount);
JVM_VirtualThreadUnmount(JNIEnv* env, jobject vthread, jboolean hide, jboolean last_unmount);

JNIEXPORT void JNICALL
JVM_VirtualThreadHideFrames(JNIEnv* env, jobject vthread, jboolean hide);
Expand Down
63 changes: 24 additions & 39 deletions src/java.base/share/classes/java/lang/VirtualThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import jdk.internal.vm.annotation.ChangesCurrentThread;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Hidden;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import jdk.internal.vm.annotation.JvmtiMountTransition;
import sun.nio.ch.Interruptible;
import sun.security.action.GetPropertyAction;
Expand Down Expand Up @@ -210,7 +211,7 @@ private void runContinuation() {
}

// notify JVMTI before mount
if (notifyJvmtiEvents) notifyJvmtiMountBegin(firstRun);
notifyJvmtiMount(true, firstRun);

try {
cont.run();
Expand Down Expand Up @@ -287,11 +288,10 @@ private void submitFailed(RejectedExecutionException ree) {
@ChangesCurrentThread
private void run(Runnable task) {
assert state == RUNNING;
boolean notifyJvmti = notifyJvmtiEvents;

// first mount
mount();
if (notifyJvmti) notifyJvmtiMountEnd(true);
notifyJvmtiMount(false, true);

// emit JFR event if enabled
if (VirtualThreadStartEvent.isTurnedOn()) {
Expand Down Expand Up @@ -319,7 +319,7 @@ private void run(Runnable task) {

} finally {
// last unmount
if (notifyJvmti) notifyJvmtiUnmountBegin(true);
notifyJvmtiUnmount(true, true);
unmount();

// final state
Expand Down Expand Up @@ -381,35 +381,27 @@ private void unmount() {

/**
* Sets the current thread to the current carrier thread.
* @return true if JVMTI was notified
*/
@ChangesCurrentThread
@JvmtiMountTransition
private boolean switchToCarrierThread() {
boolean notifyJvmti = notifyJvmtiEvents;
if (notifyJvmti) {
notifyJvmtiHideFrames(true);
}
private void switchToCarrierThread() {
notifyJvmtiHideFrames(true);
Thread carrier = this.carrierThread;
assert Thread.currentThread() == this
&& carrier == Thread.currentCarrierThread();
carrier.setCurrentThread(carrier);
return notifyJvmti;
}

/**
* Sets the current thread to the given virtual thread.
* If {@code notifyJvmti} is true then JVMTI is notified.
*/
@ChangesCurrentThread
@JvmtiMountTransition
private void switchToVirtualThread(VirtualThread vthread, boolean notifyJvmti) {
private void switchToVirtualThread(VirtualThread vthread) {
Thread carrier = vthread.carrierThread;
assert carrier == Thread.currentCarrierThread();
carrier.setCurrentThread(vthread);
if (notifyJvmti) {
notifyJvmtiHideFrames(false);
}
notifyJvmtiHideFrames(false);
}

/**
Expand All @@ -419,17 +411,15 @@ private void switchToVirtualThread(VirtualThread vthread, boolean notifyJvmti) {
*/
@ChangesCurrentThread
private boolean yieldContinuation() {
boolean notifyJvmti = notifyJvmtiEvents;

// unmount
if (notifyJvmti) notifyJvmtiUnmountBegin(false);
notifyJvmtiUnmount(true, false);
unmount();
try {
return Continuation.yield(VTHREAD_SCOPE);
} finally {
// re-mount
mount();
if (notifyJvmti) notifyJvmtiMountEnd(false);
notifyJvmtiMount(false, false);
}
}

Expand All @@ -446,7 +436,7 @@ private void afterYield() {
setState(PARKED);

// notify JVMTI that unmount has completed, thread is parked
if (notifyJvmtiEvents) notifyJvmtiUnmountEnd(false);
notifyJvmtiUnmount(false, false);

// may have been unparked while parking
if (parkPermit && compareAndSetState(PARKED, RUNNABLE)) {
Expand All @@ -462,7 +452,7 @@ private void afterYield() {
setState(RUNNABLE);

// notify JVMTI that unmount has completed, thread is runnable
if (notifyJvmtiEvents) notifyJvmtiUnmountEnd(false);
notifyJvmtiUnmount(false, false);

// external submit if there are no tasks in the local task queue
if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) {
Expand All @@ -483,7 +473,7 @@ private void afterTerminate(boolean executed) {
assert (state() == TERMINATED) && (carrierThread == null);

if (executed) {
if (notifyJvmtiEvents) notifyJvmtiUnmountEnd(true);
notifyJvmtiUnmount(false, true);
}

// notify anyone waiting for this virtual thread to terminate
Expand Down Expand Up @@ -651,11 +641,11 @@ private void parkOnCarrierThread(boolean timed, long nanos) {
@ChangesCurrentThread
private Future<?> scheduleUnpark(Runnable unparker, long nanos) {
// need to switch to current carrier thread to avoid nested parking
boolean notifyJvmti = switchToCarrierThread();
switchToCarrierThread();
try {
return UNPARKER.schedule(unparker, nanos, NANOSECONDS);
} finally {
switchToVirtualThread(this, notifyJvmti);
switchToVirtualThread(this);
}
}

Expand All @@ -666,11 +656,11 @@ private Future<?> scheduleUnpark(Runnable unparker, long nanos) {
private void cancel(Future<?> future) {
if (!future.isDone()) {
// need to switch to current carrier thread to avoid nested parking
boolean notifyJvmti = switchToCarrierThread();
switchToCarrierThread();
try {
future.cancel(false);
} finally {
switchToVirtualThread(this, notifyJvmti);
switchToVirtualThread(this);
}
}
}
Expand All @@ -690,11 +680,11 @@ void unpark() {
int s = state();
if (s == PARKED && compareAndSetState(PARKED, RUNNABLE)) {
if (currentThread instanceof VirtualThread vthread) {
boolean notifyJvmti = vthread.switchToCarrierThread();
vthread.switchToCarrierThread();
try {
submitRunContinuation();
} finally {
switchToVirtualThread(vthread, notifyJvmti);
switchToVirtualThread(vthread);
}
} else {
submitRunContinuation();
Expand Down Expand Up @@ -1055,20 +1045,15 @@ private void setCarrierThread(Thread carrier) {

// -- JVM TI support --

private static volatile boolean notifyJvmtiEvents; // set by VM

@JvmtiMountTransition
private native void notifyJvmtiMountBegin(boolean firstMount);

@JvmtiMountTransition
private native void notifyJvmtiMountEnd(boolean firstMount);

@IntrinsicCandidate
@JvmtiMountTransition
private native void notifyJvmtiUnmountBegin(boolean lastUnmount);
private native void notifyJvmtiMount(boolean hide, boolean firstMount);

@IntrinsicCandidate
@JvmtiMountTransition
private native void notifyJvmtiUnmountEnd(boolean lastUnmount);
private native void notifyJvmtiUnmount(boolean hide, boolean lastUnmount);

@IntrinsicCandidate
@JvmtiMountTransition
private native void notifyJvmtiHideFrames(boolean hide);

Expand Down
8 changes: 3 additions & 5 deletions src/java.base/share/native/libjava/VirtualThread.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,9 @@
#define VIRTUAL_THREAD "Ljava/lang/VirtualThread;"

static JNINativeMethod methods[] = {
{ "notifyJvmtiMountBegin", "(Z)V", (void *)&JVM_VirtualThreadMountBegin },
{ "notifyJvmtiMountEnd", "(Z)V", (void *)&JVM_VirtualThreadMountEnd },
{ "notifyJvmtiUnmountBegin", "(Z)V", (void *)&JVM_VirtualThreadUnmountBegin },
{ "notifyJvmtiUnmountEnd", "(Z)V", (void *)&JVM_VirtualThreadUnmountEnd },
{ "notifyJvmtiHideFrames", "(Z)V", (void *)&JVM_VirtualThreadHideFrames },
{ "notifyJvmtiMount", "(ZZ)V", (void *)&JVM_VirtualThreadMount },
{ "notifyJvmtiUnmount", "(ZZ)V", (void *)&JVM_VirtualThreadUnmount },
{ "notifyJvmtiHideFrames", "(Z)V", (void *)&JVM_VirtualThreadHideFrames },
};

JNIEXPORT void JNICALL
Expand Down

0 comments on commit b0fd761

Please sign in to comment.