RFR: 8291065: Creating a VarHandle for a static field triggers class initialization [v11]
Chen Liang
liach at openjdk.org
Tue Jun 27 14:07:11 UTC 2023
On Fri, 9 Jun 2023 18:59:41 GMT, Paul Sandoz <psandoz at openjdk.org> wrote:
>> Chen Liang has updated the pull request incrementally with one additional commit since the last revision:
>>
>> Remove meaningless target calls and clear outdated cache as needed
>
> Something was bothering me about the current complexity with method handles and the potential interactions with indirect var handles. Its hard to reason about all the interactions so i needed to take a deeper dive, which i really should have done earlier on. Apologies if we are circling around this many times.
>
> Since we are now leaning on `LazyInitializingVarHandle::target` to initialize I think we can just do this:
>
> private void initialize() {
> UNSAFE.ensureClassInitialized(refc);
> this.initialized = true;
> }
>
> @Override
> public MethodHandle toMethodHandle(AccessMode accessMode) {
> if (initialized) {
> return target.toMethodHandle(accessMode);
> } else {
> if (isAccessModeSupported(accessMode)) {
> MethodHandle mh = target.getMethodHandle(accessMode.ordinal());
> // Ensure target on this VH is called to initialize the class
> return mh.bindTo(this);
> }
> else {
> // Ensure an UnsupportedOperationException is thrown
> return MethodHandles.varHandleInvoker(accessMode, accessModeType(accessMode)).
> bindTo(this);
> }
> }
> }
>
>
> However, construction of an indirect VH will result in initialization:
>
> private IndirectVarHandle(VarHandle target, Class<?> value, Class<?>[] coordinates,
> BiFunction<AccessMode, MethodHandle, MethodHandle> handleFactory, VarForm form, boolean exact) {
> super(form, exact);
> this.handleFactory = handleFactory;
> this.target = target;
> this.directTarget = target.target();
> this.value = value;
> this.coordinates = coordinates;
> }
>
>
> Since this is not performance sensitive code we could check if target is an instance of `LazyInitializingVarHandle` then conditionally get it's target if initialized e.g.,
>
> this.directTarget = target instanceof LazyInitializingVarHandle lazyTarget ? lazyTarget.lazyTarget() : target.target();
>
> ?
@PaulSandoz I think this patch as of now is what I want:
1. Lazy VH works both when obtained directly or delegated by an Indirect VH
2. In the most common usage scenario (direct calls on VH), the lazy VH has a good initial performance and a similar long-term performance compared to the eager VH
3. The invasive changes to existing structures are minimized.
For the performance concerns of `getMethodHandle` and `toMethodHandle` (mainly creation and initial invocation), I find that the VH invocation semantics itself has some problems: for example, it's quite pointless to pass a VH-specific direct VH to a VH-specific `getMethodHandle`. My focus on this patch will be to ensure the correctness of MH-related content, but caring about their performance is out of scope for me.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/13821#issuecomment-1609577849
More information about the core-libs-dev
mailing list