RFR: 8369609: Continuations preempt_epilog is missing a call to invalidate_jvmti_stack [v3]

Serguei Spitsyn sspitsyn at openjdk.org
Thu Oct 23 03:59:02 UTC 2025


On Wed, 22 Oct 2025 22:40:16 GMT, Serguei Spitsyn <sspitsyn at openjdk.org> wrote:

>> Good idea! It'd be nice to move the `invalidate_jvmti_stack()` calls out of the continuation code. I'll test it and let you know the results.
>
> Strangely, the test `serviceability/jvmti/vthread/ContStackDepthTest` is failing with the `assert(_cur_stack_depth == num_frames)`. Obviously, some of the code paths is missed to call `invalidate_jvmti_stack()`.

As I see, the calls to `invalidate_jvmti_stack()` are needed for plain continuations only (under condition `if !cont.entry()->is_virtual_thread()`).

The following patch does not cause regressions in mach5 tier 6 (mach5 tiers 1-5 are in progress):

diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp
index 0884fce2ff7..dbbf5526602 100644
--- a/src/hotspot/share/prims/jvmtiExport.cpp
+++ b/src/hotspot/share/prims/jvmtiExport.cpp
@@ -1711,7 +1711,6 @@ void JvmtiExport::continuation_yield_cleanup(JavaThread* thread, jint continuati
   if (state == nullptr) {
     return;
   }
-  state->invalidate_cur_stack_depth();
 
   // Clear frame_pop requests in frames popped by yield
   if (can_post_frame_pop()) {
diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
index 0750f611876..b7c0c1f3f07 100644
--- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp
+++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
@@ -1626,11 +1626,14 @@ static void invalidate_jvmti_stack(JavaThread* thread) {
 }
 
 static void jvmti_yield_cleanup(JavaThread* thread, ContinuationWrapper& cont) {
-  if (!cont.entry()->is_virtual_thread() && JvmtiExport::has_frame_pops(thread)) {
-    int num_frames = num_java_frames(cont);
+  if (!cont.entry()->is_virtual_thread()) {
+    invalidate_jvmti_stack(thread);
+    if (JvmtiExport::has_frame_pops(thread)) {
+      int num_frames = num_java_frames(cont);
 
-    ContinuationWrapper::SafepointOp so(Thread::current(), cont);
-    JvmtiExport::continuation_yield_cleanup(JavaThread::current(), num_frames);
+      ContinuationWrapper::SafepointOp so(Thread::current(), cont);
+      JvmtiExport::continuation_yield_cleanup(thread, num_frames);
+    }
   }
 }
 
@@ -1685,7 +1688,7 @@ static inline freeze_result freeze_epilog(ContinuationWrapper& cont) {
 
   log_develop_debug(continuations)("=== End of freeze cont ### #" INTPTR_FORMAT, cont.hash());
 
-  JVMTI_ONLY(invalidate_jvmti_stack(JavaThread::current()));
+  JVMTI_ONLY(if (!cont.entry()->is_virtual_thread()) invalidate_jvmti_stack(JavaThread::current()));
   return freeze_ok;
 }
 
@@ -1697,7 +1700,7 @@ static freeze_result freeze_epilog(JavaThread* thread, ContinuationWrapper& cont
     return res;
   }
 
-  JVMTI_ONLY(jvmti_yield_cleanup(thread, cont)); // can safepoint
+  JVMTI_ONLY(if (!cont.entry()->is_virtual_thread()) jvmti_yield_cleanup(thread, cont)); // can safepoint
   return freeze_epilog(cont);
 }
 
@@ -2311,7 +2314,7 @@ NOINLINE intptr_t* Thaw<ConfigT>::thaw_slow(stackChunkOop chunk, Continuation::t
 
   assert(_cont.chunk_invariant(), "");
 
-  JVMTI_ONLY(invalidate_jvmti_stack(_thread));
+  JVMTI_ONLY(if (!_cont.entry()->is_virtual_thread()) invalidate_jvmti_stack(_thread));
 
   _thread->set_cont_fastpath(_fastpath);
 ```

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/27878#discussion_r2453856096


More information about the hotspot-runtime-dev mailing list