Is it necessary to check subtype for invokeinterface of private method?
Liu, Xin
xxinliu at amazon.com
Wed Nov 17 08:22:10 UTC 2021
Hi, David,
Thanks you the head-up! Now I understand why c2 generates the checkcast
code for invokespecial and invokeinterface. It must conform to the JVM
spec.
C1 does the checkcast for invokespecial right now.
https://github.com/openjdk/jdk/blob/master/src/hotspot/share/c1/c1_GraphBuilder.cpp#L1874
./test/jdk/java/lang/invoke/PrivateInterfaceCall.java is correct. The
ICCE is expected. I will implement invokeinterface by book.
I don't intend the challenge the JVM spec. The private interface methods
is new for me. I double think about this. There's no polymorphism for
them, so c1/c2 can use relocInfo::opt_virtual_call_type to optimize the
callsites of them, but the typecheck still needs to be in place!
thanks,
--lx
On 11/16/21 10:56 PM, David Holmes wrote:
> CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.
>
>
>
> 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