Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/hotspot/share/runtime/continuationFreezeThaw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,6 @@ static void jvmti_yield_cleanup(JavaThread* thread, ContinuationWrapper& cont) {
ContinuationWrapper::SafepointOp so(Thread::current(), cont);
JvmtiExport::continuation_yield_cleanup(JavaThread::current(), num_frames);
}
invalidate_jvmti_stack(thread);
}

static void jvmti_mount_end(JavaThread* current, ContinuationWrapper& cont, frame top) {
Expand Down Expand Up @@ -1685,6 +1684,8 @@ static inline freeze_result freeze_epilog(ContinuationWrapper& cont) {
assert(!cont.is_empty(), "");

log_develop_debug(continuations)("=== End of freeze cont ### #" INTPTR_FORMAT, cont.hash());

JVMTI_ONLY(invalidate_jvmti_stack(JavaThread::current()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not directly in preempt_epilog? Is it to cover the freeze fast case too? If that’s the case we should remove the call to invalidate_jvmti_stack from jvmti_yield_cleanup to avoid calling it twice for the freeze slow case. Also I wonder if this call to invalidate_jvmti_stack should just be moved to JvmtiVTMSTransitionDisabler::VTMS_unmount_end instead.

Copy link
Contributor Author

@sspitsyn sspitsyn Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the comment! Yes, I had in mind but forgot to remove the call to invalidate_jvmti_stack() from jvmti_yield_cleanup(). I've pushed the update now.

Also I wonder if this call to invalidate_jvmti_stack should just be moved to JvmtiVTMSTransitionDisabler::VTMS_unmount_end instead.

Unfortunately, this is not going to work for plain/pure continuations as mount/unmount code path does not work for them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. What do you think about adding invalidate_jvmti_stack in jvmti_yield_cleanup if !cont.entry()->is_virtual_thread() is true to address that case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

@sspitsyn sspitsyn Oct 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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().

Copy link
Contributor Author

@sspitsyn sspitsyn Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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..f8406fb33c1 100644
--- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp
+++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
@@ -1626,11 +1626,15 @@ 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)) {
+  if (cont.entry()->is_virtual_thread()) {
+    return;
+  }
+  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);
+    JvmtiExport::continuation_yield_cleanup(thread, num_frames);
   }
 }
 
@@ -1685,7 +1689,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;
 }
 
@@ -2311,7 +2315,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);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, we need to call invalidate_jvmti_stack at the end in jvmti_yield_cleanup! The problem is that in JvmtiExport::continuation_yield_cleanup we are setting again the stack depth when calling state->cur_stack_depth(). We count the enterSpecial frame at the top but we don’t decrement the depth when removing it (done in assembly code).

return freeze_ok;
}

Expand Down