RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v11]

Chen Liang liach at openjdk.org
Mon May 1 22:36:27 UTC 2023


On Mon, 1 May 2023 21:00:40 GMT, John R Rose <jrose at openjdk.org> wrote:

> I think you could do this by having the HC have a final non-static field for each required MH (one per overload point); each os an asType adaptation of the original MH. The actual code of each HC implementation method would be a single invokeVirtual of a strongly typed MH::invokeExact call. This is the code shape in the current PR (see the createTemplate method) except that I am saying that the MH in question should come from getfield not ldc/condy.

This was the implementation up to [953fcc9f](https://git.openjdk.org/jdk/pull/13197/files/953fcc9fdb4bb80389c770b585d5f9b4d3936947) (webrev 0). It had an invocation performance of 2ns/op as opposed to Proxy's 6ns/op, but the condy implementation has 0.41ns/op.

I indeed can move the argument validation (with a jdk.internal object instance, will add to wrapperInstanceType and wrapperInstanceTarget to avoid method clashes) and marker interface into jdk.internal.access.invoke package and export it to the HC's module (thanks to mandy for the patch). And moving `asType` to the constructor is viable too; we just need to propagate the thrown `WrongMethodTypeException` to the caller.

So assuming the methodhandle-in-field approach has good performance, we will probably generate something like:

package jdk.MHProxy5;
import sun.invoke.empty.Empty;
import sun.invoke.WrapperInstance;
//...
final /*synthetic*/ class Iface$MHProxy implements Iface, WrapperInstance {
    final MethodHandle originalMh, mh1, mh2, ...;
    // no access worries, in a non-open module, users cannot call
    Iface$MHProxy(MethodHandle originalMh, MethodHandle mh) {
        this.originalMh = originalMh; // possibly didn't bind caller
        this.mh1 = mh.asType(/*ldc MethodType */);
        //...
    }
    // Iface implementations
    public R singleMethod(P0 p0, ...) { try { return mh1.invokeExact(p0, ...); /* explicit descriptor */ } catch ... (rethrow, wrap throw)
    // ...
    // WrapperInstance implementations
    public Class<?> wrapperType(Empty empty) { return Iface$MHProxy.class; } // unused Empty parameter prevents method clash
    public MethodHandle wrapperTarget(Empty empty) {return originalMh;}
}


For proxy code, I think they look up the set of interfaces and generate one class in one module for each set, which is close to the single-class + module implementation outlined above.

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

PR Comment: https://git.openjdk.org/jdk/pull/13197#issuecomment-1530438142


More information about the core-libs-dev mailing list