> If a thread tries to initialize a class that is already being initialized by 
> another thread, it will block until notified. Since at this blocking point 
> there are native frames on the stack, a virtual thread cannot be unmounted 
> and is pinned to its carrier. Besides harming scalability, this can, in some 
> pathological cases, lead to a deadlock, for example, if the thread executing 
> the class initialization method is blocked waiting for some unmounted virtual 
> thread to run, but all carriers are blocked waiting for that class to be 
> initialized.
> 
> As of JDK-8338383, virtual threads blocked in the VM on `ObjectMonitor` 
> operations can be unmounted. Since synchronization on class initialization is 
> implemented using `ObjectLocker`, we can reuse the same mechanism to unmount 
> virtual threads on these cases too.
> 
> This patch adds support for unmounting virtual threads on some of the most 
> common class initialization paths, specifically when calling 
> `InterpreterRuntime::_new` (`new` bytecode), and 
> `InterpreterRuntime::resolve_from_cache` for `invokestatic`, `getstatic` or 
> `putstatic` bytecodes. In the future we might consider extending this 
> mechanism to include initialization calls originating from native methods 
> such as `Class.forName0`.
> 
> ### Summary of implementation
> 
> The ObjectLocker class was modified to not pin the continuation if we are 
> coming from a preemptable path, which will be the case when calling 
> `InstanceKlass::initialize_impl` from new method 
> `InstanceKlass::initialize_preemptable`. This means that for these cases, a 
> virtual thread can now be unmounted either when contending for the init_lock 
> in the `ObjectLocker` constructor, or in the call to `wait_uninterruptibly`. 
> Also, since the call to initialize a class includes a previous call to 
> `link_class` which also uses `ObjectLocker` to protect concurrent calls from 
> multiple threads, we will allow preemption there too.
> 
> If preempted, we will throw a pre-allocated exception which will get 
> propagated with the `TRAPS/CHECK` macros all the way back to the VM entry 
> point. The exception will be cleared and on return back to Java the virtual 
> thread will go through the preempt stub and unmount. When running again, at 
> the end of the thaw call we will identify this preemption case and redo the 
> original VM call (either `InterpreterRuntime::_new` or 
> `InterpreterRuntime::resolve_from_cache`). 
> 
> ### Notes
> 
> `InterpreterRuntime::call_VM_preemptable` used previously only for 
> `InterpreterRuntime::monitorenter`, was renamed to `In...

Patricio Chilano Mateo has updated the pull request with a new target base due 
to a merge or a rebase. The pull request now contains four commits:

 - Merge branch 'master' into JDK-8369238
 - RISC-V support
 - Fix whitespaces
 - v1

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

Changes: https://git.openjdk.org/jdk/pull/27802/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27802&range=01
  Stats: 1979 lines in 94 files changed: 1628 ins; 86 del; 265 mod
  Patch: https://git.openjdk.org/jdk/pull/27802.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/27802/head:pull/27802

PR: https://git.openjdk.org/jdk/pull/27802

Reply via email to