On Tue, 3 Nov 2026 20:46:56 GMT, Shiv Shah <[email protected]> wrote:

>> When a virtual thread suspended at a breakpoint gets unmounted and mounted 
>> again only the top frame is thawed. The caller stays frozen in the stack 
>> chunk and the popped frame returns into the continuation return barrier. The 
>> interpreter's popframe entry treats that return address like a deoptimized 
>> caller, preserves the arguments, sets the reexecution bit and returns. The 
>> barrier then thawed the caller as a plain return. Arguments and bit left 
>> behind, no reexecution of the invoke, run() went on with a zero result.
>> 
>> Thaw finishes it now. An interpreted caller gets the preserved arguments 
>> back on its expression stack and its return slot is patched to a new 
>> popframe reexecution entry of the interpreter, the mdp is set back to the 
>> invoke as well. A compiled caller frozen in the chunk is deoptimized from 
>> UpdateForPopTopFrameClosure::doit the same way set_frame_pop does it. Thaw 
>> leaves the arguments alone in that case and unpack_on_stack puts them back. 
>> A frozen compiled frame being popped stays opaque.
>> 
>> A linkTo caller needs one more thing. The linker consumed the trailing 
>> MemberName before the target ran and the preserved arguments are sized by 
>> the target, so the MemberName is not among them. Thaw takes it from the 
>> caller's local 0 the way the interpreter's popframe entry does, the lookup 
>> from member_name_arg_or_null moved into a plain helper both can call. The 
>> arguments go one slot up and the MemberName goes back on top.
>> 
>> popframes002 runs popframes001 on a virtual thread with the join Chris 
>> Plummer wrote enabled by a property in the debuggee. It unmounts the tested 
>> thread before the breakpoint so the caller is frozen when popped, and run() 
>> is excluded from compilation so this stays the interpreted case. 
>> popframes003 is the compiled caller case, -Xcomp with the breakpoint in a 
>> separate stop() so testedMethod keeps its compiled frame and run() stays 
>> frozen, the debugger pops frame 1 and the debuggee checks with WhiteBox that 
>> run() and testedMethod are compiled and that testedMethod ran twice. 
>> -XX:+PreserveFramePointer keeps the thaw on the slow path. Both fail on 
>> master without the hotspot change. popframes001 itself runs the plain case 
>> as before and is off the virtual problem list. If separate copies of the 
>> debugger and debuggee are preferred over the properties that is easy to 
>> change. PopFrameMethodNameInvariantTest got an unmount mode, the same 
>> linkToStatic pop on a virtual thread that sleeps
 before the breakpoint so its caller is frozen.
>> 
>>...
>
> Shiv Shah has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Comments on the frozen frame checks and the two deoptimization paths

test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001a.java 
line 96:

> 94:         }
> 95: 
> 96:         // the popped frame runs again, so the tested method is invoked 
> exactly twice

Nit: The comment is confusing a little bit. I'd suggest to say:
       `// the tested method is expected to be invoked twice

test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/PopFrames/popframes001a.java 
line 149:

> 147:                 // The first join unmounts the tested thread, leaving 
> its caller in the
> 148:                 // heap when PopFrame is executed. Code before this join 
> must not deoptimize
> 149:                 // this frame, as thawing an interpreted frame also 
> thaws its compiled caller.

Nit: This comment is not easy to understand. The context need to be explained 
that the `testedMethod()` is invoked two times because of the JVMTI `PopFrame`.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/32661#discussion_r4475282864
PR Review Comment: https://git.openjdk.org/jdk/pull/32661#discussion_r4475413676

Reply via email to