RFR: 8369609: Continuations preempt_epilog is missing a call to invalidate_jvmti_stack [v3]
Serguei Spitsyn
sspitsyn at openjdk.org
Thu Oct 23 17:20:59 UTC 2025
On Thu, 23 Oct 2025 14:24:05 GMT, Patricio Chilano Mateo <pchilanomate at openjdk.org> wrote:
>> 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_fast...
>
> 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).
Okay, thanks! Did you verify it the test `serviceability/jvmti/vthread/ContStackDepthTest`? I see it is still failing.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/27878#discussion_r2456206623
More information about the hotspot-runtime-dev
mailing list