This PR proposes to improve the initialization and access performance of `LazyConstantImpl`.
## Tiered access ## The first-tier (already-initialized) fast path in `get()` remains `@ForceInline` and contains only a minimal _acquire_ load of the computed constant, a null check, and a cast. A second-tier method, which includes the successful computation path, is no longer annotated with `@DontInline`, allowing the C2 to make its own inlining decisions. In tier three, contention handling and exceptional paths are further isolated in a `@DontInline` method and other helper methods. ## Other optimizations ## The previous monitor-based initialization with `synchronized` and the recursive detection via the native method `Thread.holdsLock()` are replaced by a CAS-based _state machine_. A new `state` field can now represent the initial supplier, the computing thread, registered waiters, or a terminal success/failure state. Normally, the computing `Thread` object is stored directly, but in the unusual case a `Thread` also implements `Supplier`, the scheme falls back to using a boxed `Long`, keeping the statemachine types disjoint. Contending threads initially spin, followed by short randomized timed backoffs. If computation is still in progress, they register in a waiting queue and park until signalled by the computing thread. Virtual threads use significantly less spinning and timed waiting to limit carrier thread and scheduler pressure. Completion atomically detaches and signals registered waiters on both successful and failed computations. Interrupted waiters retain their interrupt status, and spurious wakeups are handled by rechecking the `state`. The polling loop uses _opaque_ `state` loads while the `state` remains unchanged (for optimal performance on weaker platforms) and then performs a final _acquire_ load before acting on the state transition. Publication of the computed constant continues to use _acquire_/_release_ semantics. The constructor deliberately initializes the _volatile_ `state` using a direct store to avoid bootstrap issues. ## Tests ## The PR also proposes to add several new tests and a new benchmark that tests dynamic performance when creating and using `LazyConstant` instances on the fly. On multiple platforms, this branch passes testing in: - [x] tier1 - [x] tier2 - [x] tier3 - [x] tier4 ## Future work ## Similar schemes may be introduced in `LazyConstants` under a separate PR. --------- - [x] I confirm that I make this contribution in accordance with the [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai). ------------- Commit messages: - Fix bootstrap issue - Merge branch 'master' into rfe-lazyconstant-performance - Add a dynamic benchmark - Add special handling for VTs - Use waiters to improve discovery latency - Transition to opaque semantic in the hot loop - Use CAE instead of CAS and move checks - Improve performance - Eliminate Long boxing - Use CAS instead of synchronized - ... and 2 more: https://git.openjdk.org/jdk/compare/64e0cf41...e8aa625b Changes: https://git.openjdk.org/jdk/pull/32450/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=32450&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8390381 Stats: 571 lines in 4 files changed: 471 ins; 20 del; 80 mod Patch: https://git.openjdk.org/jdk/pull/32450.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/32450/head:pull/32450 PR: https://git.openjdk.org/jdk/pull/32450
