Is it necessary to check subtype for invokeinterface of private method?

Liu, Xin xxinliu at amazon.com
Tue Nov 16 09:44:13 UTC 2021


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.

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?

    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.

thanks,
--lx



More information about the hotspot-dev mailing list