RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v11]
Rémi Forax
forax at openjdk.org
Tue May 2 09:33:29 UTC 2023
On Mon, 1 May 2023 14:56:27 GMT, Chen Liang <liach at openjdk.org> wrote:
>> As John Rose has pointed out in this issue, the current j.l.r.Proxy based implementation of MethodHandleProxies.asInterface has a few issues:
>> 1. Exposes too much information via Proxy supertype (and WrapperInstance interface)
>> 2. Does not allow future expansion to support SAM[^1] abstract classes
>> 3. Slow (in fact, very slow)
>>
>> This patch addresses all 3 problems:
>> 1. It implements proxies with one hidden class for each requested interface and replaced WrapperInstance inheritance with a check to the class data. This can avoid unexpected passing of `instanceof`, and avoids the nasty problem of exporting a JDK interface to a dynamic module to ensure access.
>> 2. This patch obtains already generated classes from a ClassValue by the requested interface type; the ClassValue can later be updated to compute implementation generation for abstract classes as well.
>> 3. This patch's generated hidden classes has call performance on par with those of lambda expressions; the creation performance is slightly less than that of LambdaMetafactory: https://jmh.morethan.io/?gist=fcb946d83ee4ac7386901795ca49b224
>>
>> Additionally, an obsolete `ProxyForMethodHandle` test was removed, for it's no longer applicable. Tests in `jdk/java/lang/invoke` and `jdk/java/lang/reflect` pass.
>>
>> [^1]: single abstract method
>
> Chen Liang has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 24 additional commits since the last revision:
>
> - Renames
> - Merge branch 'master' into explore/mhp-iface
> - Consolidate iteration over public methods
> - Define MH proxy class in a dynamic module
> - Fix test that depend on WrapperInstance
> - Require an original lookup in constructor arguments to prevent unintended instantiation
> - pass interface info via condy,
> drop explicit ea flags
> initialize benchmark work variable randomly
> benchmarks just need 1 fork
> - Nuke WrapperInstance
> - Merge branch 'master' into explore/mhp-iface
> - Whitespace, cleanup, rename benchmarks to be informative
> - ... and 14 more: https://git.openjdk.org/jdk/compare/c212c27d...f5d0ef0a
This is the method/class specialization problem all other again.
As Jorn said, we should use the same strategy as with the lambda metafactory, one hidden class per method handle, given that otherwise it's too easy to have profile pollution. This implementation already cache the bytecode so specializing different method handles with the same interfaces + classloader reuse the same bytecode.
I really hope that with Valhalla specialized generics, we will be able share more by specializing the same proxy class with different method handles, each one acting as a constant. So one class for all, but one species per method handle.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/13197#issuecomment-1531164433
More information about the core-libs-dev
mailing list