On Fri, 22 May 2026 09:47:16 GMT, Serguei Spitsyn <[email protected]> wrote:

>> This change fixes a long standing performance issue related to the debugger 
>> single stepping that is using JVMTI `FramePop` events as a part of step over 
>> handling. The performance issue is that the target thread continues its 
>> execution in very slow `interp-only` mode in a context of frame marked for 
>> `FramePop` notification with the JVMTI `NotifyFramePop`. It includes other 
>> method calls recursively upon a return from the frame.
>> 
>> This fix is to avoid enforcing the `interp-only` execution mode for threads 
>> when `FramePop` events are enabled with the JVMTI 
>> `SetEventNotificationMode()`. Instead, the target frame has been deoptimized 
>> and kept interpreted by disabling `OSR` optimization by the function 
>> `InterpreterRuntime::frequency_counter_overflow_inner()`. (Big thanks to 
>> @fisk for this suggestion!) Additionally, some tweaks are applied in several 
>> places where the `java_thread->is_interp_only_mode()` is checked.
>> The other details will be provided in the first PR request comment.
>> 
>> Testing:
>>  - test `serviceability/jvmti/vthread/ThreadStateTest` was updated to 
>> provide some extra test coverage
>>  - submitted mach5 tiers 1-6
>> 
>> - [x] I confirm that I make this contribution in accordance with the 
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> Serguei Spitsyn has updated the pull request incrementally with one 
> additional commit since the last revision:
> 
>   review: 1. Add asserts, rem comment 2. Remove can_generate_frame_pop_events 
> from can_generate_interpreter_events

This is expected. In the 
[IDEA-292196](https://youtrack.jetbrains.com/issue/IDEA-292196) example the 
debugger is going to single step into foo(). Once in foo() it will turn off 
single stepping and do a NotifyFramePop on foo(). The FramePop is the signal to 
enable single stepping again, so for most of this test runs with single 
stepping disabled. However, the NotifyFramePop on foo() forces foo() to be 
interpreted, which is why it runs slow. Thsi PR does not get rid of the 
requirement that NotifyFramePop be interpreted. The fix is that the whole 
thread no longer has to be interpreted, ust the NotifyFramePop frame. You do 
see a bit of a speedup though since increment() is compiled.

In the 2nd example given above, foo() just calls foo2(), which is where all the 
work is done. So foo() is interpreted, but foo2() can be compiled. Since all 
the work is done in foo2(), it runs in 3ms.

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

PR Comment: https://git.openjdk.org/jdk/pull/28407#issuecomment-4905795215

Reply via email to