On Fri, 21 Feb 2025 23:17:50 GMT, John R Rose <[email protected]> wrote:
>> LF editor spins classes, this avoids the spinning overhead and should speed
>> up non-capturing lambdas too.
>>
>> There may need to be additional intrinsic work for MH combinator lf bytecode
>> generation.
>
> src/java.base/share/classes/java/lang/invoke/LambdaForm.java line 1653:
>
>> 1651: }
>> 1652:
>> 1653: private static LambdaForm computeConstantForm(BasicType type) {
>
> I think the word "create" is more conventional, at this point, than "compute".
> When you are finding some lazily computed resource, you create it if not
> present.
> There is "computeInvoker" and "computeValueConversions" elsewhere, but I
> think "create" is more frequent.
Renamed to `createConstantForm`.
> src/java.base/share/classes/java/lang/invoke/LambdaForm.java line 1665:
>
>> 1663: if (cached != null)
>> 1664: return cached;
>> 1665: return BASIC_SPECIES[ord] =
>> SimpleMethodHandle.BMH_SPECIES.extendWith(type);
>
> It's not clear to me what `BASIC_SPECIES` means here. BMH species exist
> which correspond to all non-empty tuples of bound types. So maybe what you
> are caching here is unary BMH species? In that case `UNARY_BMH_SPECIES`
> might be more to the point. Even better, place that array in BMH.java
> itself, call it `BoundMethodHandle.UNARY_SPECIES`, and give it a name
> `BoundMethodHandle.unarySpeciesData(BasicType)`.
I just noticed `BMH$SpeciesData.extensions` is a stable array, so we can just
query `SimpleMethodHandle.BMH_SPECIES` (aka `BMH.SPECIALIZER.topSpecies`)'s
`extendWith` and use that stable array instead.
> src/java.base/share/classes/java/lang/invoke/LambdaForm.java line 1691:
>
>> 1689:
>> 1690: // Look up symbolic names. It might not be necessary to
>> have these,
>> 1691: // but if we need to emit direct references to bytecodes,
>> it helps.
>
> Rename `createFormsFor` to `createIdentityForm`, since it now only creates
> that one thing (plus its NF).
Done.
> src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java line 1347:
>
>> 1345: IDENTITY,
>> 1346: CONSTANT,
>> 1347: NONE // no intrinsic associated
>
> I notice you are using the `intrinsicData` property to keep track of the
> constant, which is a good call.
>
> A little below here, around line 1400, there is a possible bug in the
> handling of `intrinsicData`.
>
> Possible fix:
>
>
> --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
> +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
> @@ -1409,7 +1409,8 @@ static MethodHandle makeIntrinsic(MethodHandle target,
> Intrinsic intrinsicName)
> }
>
> static MethodHandle makeIntrinsic(MethodHandle target, Intrinsic
> intrinsicName, Object intrinsicData) {
> - if (intrinsicName == target.intrinsicName())
> + if (intrinsicName == target.intrinsicName() &&
> + intrinsicData == target.intrinsicData())
> return target;
> return new IntrinsicMethodHandle(target, intrinsicName,
> intrinsicData);
> }
>
>
> It should be added to this PR, lest constants get confused somehow.
I reviewed the other use of `intrinsicData`, `tableSwitch`. I believe the
intrinsic is actually a regression by growing the bytecode size - we should
just select a MH via hash table lookup and invoke that MH, given all MHs in
that list have the same type. I have removed the use of intrinsic data here and
we can move on to remove it later.
I noticed that intrinsics are useful really only as part of named functions.
And named functions only reuse arbitrary MHs for the invoker form. Is my
understanding here correct?
> src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java line 2307:
>
>> 2305: }
>> 2306:
>> 2307: static MethodHandle makeConstantI(Wrapper type, int value) {
>
> After going over the rest of the patch, I don't think these new factories
> pull their weight.
>
> They just duplicate what the BMH species factories do when adding the first
> bound value.
>
> If the BMH factories don't do this job, they should be changed so they can
> handle it.
>
> In other words, the details of BMH factory invocation should be kept inside
> the BMH files (or SMH, which is the null case of BMH).
Addressed in the same way as for
https://github.com/openjdk/jdk/pull/23706#discussion_r1968478226
> src/java.base/share/classes/java/lang/invoke/MethodHandles.java line 4946:
>
>> 4944: } else if (bt == BasicType.D_TYPE) {
>> 4945: return MethodHandleImpl.makeConstantD(0.0D);
>> 4946: }
>
> This if/then/else over basic types is unpleasantly messy, just to handle
> one-time creation for a cached zero MH.
>
> I suggest using `bt.basicTypeWrapper().zero()` to get the zero value
> generically, and then use generic binding logic such as
> `MHs::insertArguments` or `insertArgumentPrimitive`, just like
> `MHs::constant` does. Calling `makeConstantJ` and siblings seems like a code
> smell. Is there a way to get rub of `makeConstantX` and instead generalize
> the `insertArguments` protocols which creates BMHs?
I moved the binding logic to be with `BMH::bindSingle` and renamed the original
bindSingle to be bindSingleL. It should reduce code smell a little bit; will
push soon ™
> src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java line 75:
>
>> 73: LF_INVINTERFACE = 4,
>> 74: LF_INVSTATIC_INIT = 5, // DMH invokeStatic with
>> <clinit> barrier
>> 75: LF_INTERPRET = 6, // LF interpreter, only
>> its vmentry is used
>
> Unrelated change here?
Indeed, however its dummy LF used the zero NF and required some updates :( Wish
we can just cache it as a MemberName
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/23706#discussion_r1968532132
PR Review Comment: https://git.openjdk.org/jdk/pull/23706#discussion_r1968472249
PR Review Comment: https://git.openjdk.org/jdk/pull/23706#discussion_r1968500456
PR Review Comment: https://git.openjdk.org/jdk/pull/23706#discussion_r1968485136
PR Review Comment: https://git.openjdk.org/jdk/pull/23706#discussion_r1968479670
PR Review Comment: https://git.openjdk.org/jdk/pull/23706#discussion_r1968478226
PR Review Comment: https://git.openjdk.org/jdk/pull/23706#discussion_r1968479177