Is it necessary to check subtype for invokeinterface of private method?
David Holmes
david.holmes at oracle.com
Wed Nov 17 06:56:23 UTC 2021
Hi Xin,
On 16/11/2021 7:44 pm, Liu, Xin wrote:
> Hi,
>
> I am working on the regex performance in JDK-8274983. Even though it
> begins with regex, the problem boils down to invokeinterface to the
> private interface methods. Before hidden class (JDK-8238358), lambda
> meta factory generates invokespecial for them. Now it generates
> invokeinterface instead. C1 doesn't recognize the new code pattern and
> generates an ic virtual call for the callsite. If many classes all
> implement a common interface, they trash the ic stub because the
> concrete classes are different. InvokePrivateInterfaceMethod.java with
> -XX:+TraceCallFixup can reveal this pathological slowness.
>
> Is it the intentional behavior of C1? I see that C2 actually generates
> checkcast code sequence for this case. I would like to patch up C1
> because C1 plays an important role for the startup time.
Can't comment on C1 issue.
> I have a patch to let C1 treats invokeinterface private interface
> methods as invokespecial. In other words, I treat the private interface
> methods as effective final. It runs pretty well until I encounter the
> regression ./test/jdk/java/lang/invoke/PrivateInterfaceCall.java. That
> leads me to the second question.
>
> In my understanding, the code unsafeCastI2() is essentially a typecast
> of a function pointer, isn't it? My take of "unsafe" in "unsafeCastI2"
> is that its behavior undefined, then why we need to check ICCE here?
"unsafe" means that the validity of the cast can't be checked
immediately, but it will be checked when the result is actually used -
it is not "undefined behaviour". The VM and MethodHandle specifications
require the subtype check on the receiver:
JVMS 6.5 invoke_interface - Run-time Exception: Otherwise, if the class
of objectref does not implement the resolved interface, invokeinterface
throws an IncompatibleClassChangeError.
> System.out.println("ICCE PrivateInterfaceCall.invokeDirect D1");
> shouldThrowICCE(() ->
> PrivateInterfaceCall.invokeDirect(unsafeCastI2(new D1())))
>
> static I2 unsafeCastI2(Object obj) {
> try {
> MethodHandle mh = MethodHandles.identity(Object.class);
> mh = MethodHandles.explicitCastArguments(mh,
> mh.type().changeReturnType(I2.class));
> return (I2)mh.invokeExact((Object) obj);
> } catch (Throwable e) {
> throw new Error(e);
> }
> }
>
> In real world, how much meaningful we detect the error if we
> accidentally invoke a private interface method where we actually don't
> implement that interface. I think it's only possible via methodhandle
> and jasm, right? if we say it's undefined behavior, I think we can skip
> typecheck. It would make lambda code faster.
I think there are potential security considerations here, but if you
want to make a case for change then email:
jls-jvms-spec-comments at openjdk.java.net
Cheers,
David
> thanks,
> --lx
>
More information about the hotspot-dev
mailing list