On Jan 15, 2014, at 11:41 AM, Vladimir Ivanov <vladimir.x.iva...@oracle.com> wrote:
> Chris, > > Thanks for looking into this. See my answers inline. > > Best regards, > Vladimir Ivanov > > On 1/15/14 9:51 PM, Christian Thalinger wrote: >> [I’m resending something I sent earlier today to Vladimir directly.] >> >> On Jan 15, 2014, at 7:31 AM, Vladimir Ivanov <vladimir.x.iva...@oracle.com> >> wrote: >> >>> http://cr.openjdk.java.net/~vlivanov/8031502/webrev.00/ >>> https://bugs.openjdk.java.net/browse/JDK-8031502 >>> >>> InvokeBytecodeGenerator can produce incorrect bytecode for a LambdaForm >>> when invoking a method from Object declared in an interface. >>> >>> The problem is the following: >>> (1) java.lang.CharSequence interface declares abstract method "String >>> toString()"; >>> >>> (2) after 8014013 fix, VM resolves >>> CharSequence::toString()/invokeInterface to >>> CharSequence::toString()/invokeVirtual; >> >> Without having looked at the changes of 8014013, why did the invoke type >> change? Is it an optimization that was added? >> > > After 8014013, LinkResolver::resolve_interface_call returns virtual > (_call_kind = CallInfo::vtable_call), instead of interface method and > MethodHandles::init_method_MemberName uses it as is (without any fine > tuning, which was done before). > > It's caused by the following: > - LinkResolver::linktime_resolve_interface_method returns > CharSequence::toString method, but it has vtable index, instead of > itable index; > > - LinkResolver::runtime_resolve_interface_method looks at resolved > method and sets _call_kind to vtable_call, since resolved method doesn't > have itable index. > > - then MethodHandles::init_method_MemberName looks at CallInfo passed > in and sets the reference kind flag to JVM_REF_invokeVirtual. > > That's how the conversion from invokeInterface to invokeVirtual occurs. > > I did a quick debugging session with pre-8014013 hotspot to check how it > worked before, but don't remember all the details now. > >>> >>> (3) during LambdaForm compilation, CharSequence is considered >>> statically invocable (see >>> InvokeBytecodeGenerator::isStaticallyInvocable) and invokevirtual for >>> CharSequence::toString() is issued, which is wrong (invokevirtual throws >>> ICCE if it references an interface); >>> >>> The fix is straightforward: during LambdaForm compilation, switch back >>> from invokevirtual to invokeinterface instruction when invoking a method >>> on an interface. >> >> I find this risky. Right now MemberName is only used in a couple places in >> java.lang.invoke but in the future it might be used for other things (e.g. >> java.lang.reflect). The information MemberName contains should be correct >> and usable without changing. Otherwise all users have to patch the >> information the same way as you do in your patch. >> >> I would like to see the VM passing correct information (whatever the >> definition of correct is here). >> > > It's an interesting question what kind of correctness is required for > MemberName and I don't know the answer. Looking through the code, I got > an impression MemberName isn't designed to provide information to be > used "as is" for bytecode generation, because, at least: > - MemberName::referenceKindIsConsistent already expects > (clazz.isInterface() && refKind == REF_invokeVirtual && > isObjectPublicMethod()) case; > > - InvokeBytecodeGenerator::emitStaticInvoke already has a special > case for REF_invokeSpecial referenceKind, converting it to > REF_invokeVirtual; John would know the answer. Given this change should go into JDK 8 I think we should push for now. If we can come up with a better way to handle these situations we can push another change for 9 or 8u20. > > Best regards, > Vladimir Ivanov > _______________________________________________ > mlvm-dev mailing list > mlvm-...@openjdk.java.net > http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev