On Tue, 29 Oct 2024 02:09:24 GMT, Dean Long <dl...@openjdk.org> wrote:
>> This is the implementation of JEP 491: Synchronize Virtual Threads without >> Pinning. See [JEP 491](https://bugs.openjdk.org/browse/JDK-8337395) for >> further details. >> >> In order to make the code review easier the changes have been split into the >> following initial 4 commits: >> >> - Changes to allow unmounting a virtual thread that is currently holding >> monitors. >> - Changes to allow unmounting a virtual thread blocked on synchronized >> trying to acquire the monitor. >> - Changes to allow unmounting a virtual thread blocked in `Object.wait()` >> and its timed-wait variants. >> - Changes to tests, JFR pinned event, and other changes in the JDK libraries. >> >> The changes fix pinning issues for all 4 ports that currently implement >> continuations: x64, aarch64, riscv and ppc. Note: ppc changes were added >> recently and stand in its own commit after the initial ones. >> >> The changes fix pinning issues when using `LM_LIGHTWEIGHT`, i.e. the default >> locking mode, (and `LM_MONITOR` which comes for free), but not when using >> `LM_LEGACY` mode. Note that the `LockingMode` flag has already been >> deprecated ([JDK-8334299](https://bugs.openjdk.org/browse/JDK-8334299)), >> with the intention to remove `LM_LEGACY` code in future releases. >> >> >> ## Summary of changes >> >> ### Unmount virtual thread while holding monitors >> >> As stated in the JEP, currently when a virtual thread enters a synchronized >> method or block, the JVM records the virtual thread's carrier platform >> thread as holding the monitor, not the virtual thread itself. This prevents >> the virtual thread from being unmounted from its carrier, as ownership >> information would otherwise go wrong. In order to fix this limitation we >> will do two things: >> >> - We copy the oops stored in the LockStack of the carrier to the stackChunk >> when freezing (and clear the LockStack). We copy the oops back to the >> LockStack of the next carrier when thawing for the first time (and clear >> them from the stackChunk). Note that we currently assume carriers don't hold >> monitors while mounting virtual threads. >> >> - For inflated monitors we now record the `java.lang.Thread.tid` of the >> owner in the ObjectMonitor's `_owner` field instead of a JavaThread*. This >> allows us to tie the owner of the monitor to a `java.lang.Thread` instance, >> rather than to a JavaThread which is only created per platform thread. The >> tid is already a 64 bit field so we can ignore issues of the counter >> wrapping around. >> >> #### General notes about this part: >> >> - Since virtual th... > > src/hotspot/cpu/x86/c1_Runtime1_x86.cpp line 223: > >> 221: } >> 222: >> 223: void StubAssembler::epilogue(bool use_pop) { > > Is there a better name we could use, like `trust_fp` or `after_resume`? I think `trust_fp` would be confusing because at this point rfp will have an invalid value and we don't want to use it to restore sp, i.e. we should not trust fp. And `after_resume` wouldn't always apply since we don't always preempt. The `use_pop` name was copied form x64, but I think it's still fine here. We also have the comment right below this line which explains why we don't want to use `leave()` and instead pop the top words from the stack. > src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp line 324: > >> 322: movq(scrReg, tmpReg); >> 323: xorq(tmpReg, tmpReg); >> 324: movptr(boxReg, Address(r15_thread, JavaThread::lock_id_offset())); > > I don't know if it helps to schedule this load earlier (it is used in the > next instruction), but it probably won't hurt. I moved it before `movq(scrReg, tmpReg)` since we need `boxReg` above, but I don't think this will change anything. > src/hotspot/share/runtime/continuationFreezeThaw.cpp line 1659: > >> 1657: int i = 0; >> 1658: for (frame f = freeze_start_frame(); >> Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map), i++) { >> 1659: if (!((f.is_compiled_frame() && !f.is_deoptimized_frame()) || (i >> == 0 && (f.is_runtime_frame() || f.is_native_frame())))) { > > OK, `i == 0` just means first frame here, so you could use a bool instead of > an int, or even check for f == freeze_start_frame(), right? Changed to use boolean `is_top_frame`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/21565#discussion_r1831594384 PR Review Comment: https://git.openjdk.org/jdk/pull/21565#discussion_r1831597325 PR Review Comment: https://git.openjdk.org/jdk/pull/21565#discussion_r1831599268