On Mon, 1 May 2023 21:00:40 GMT, John R Rose <jr...@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