Looks good!

Thank you so much David and Vladimir for all the work to cover the corner cases.

thanks,
Karen

> On Apr 26, 2018, at 12:12 AM, David Holmes <david.hol...@oracle.com> wrote:
> 
> Revised webrev: http://cr.openjdk.java.net/~dholmes/8200167/webrev.v2/
> 
> Karen formulated an additional test scenario invoking Object methods through 
> an interface reference, which when turned into a new testcase demonstrated 
> that the receiver typecheck was also missing in that case for Methodhandle's 
> from findSpecial.
> 
> Again Vladimir Ivanov formulated the fix for this. Thanks Vladimir!
> 
> Summary of changes from original webrev:
> 
> - We introduce a new version of DirectMethodHandle.preparedlambdaForm that 
> takes the caller class as a parameter, and that class is checked for being an 
> interface (not the method's declaring class) to trigger the switch to 
> LF_SPECIAL_IFC. (This obviously addresses one problem with invoking Object 
> methods - as Object is not an interface - but by itself did not fix the 
> problem.)
> 
> - We introduce a new LambdaForm kind, DIRECT_INVOKE_SPECIAL_IFC, which we use 
> when dealing with LF_INVSPECIAL_IFC. (This was the key in ensuring the 
> receiver typecheck via Special.checkReceiver remained in the generated code.)
> 
> - In the test we:
>  - introduce a new invokeDirect testcase for Object.toString(), but we need 
> to do that via a modified jcod file (as javac generates an invokevirtual)
>  - introduce the new invokeSpecialObjectMH(I2 i) call for the MH case.
> 
> Thanks,
> David
> 
> On 17/04/2018 6:48 PM, David Holmes wrote:
>> Bug: https://bugs.openjdk.java.net/browse/JDK-8200167
>> webrev: http://cr.openjdk.java.net/~dholmes/8200167/webrev/
>> Credit to John Rose and Vladimir Ivanov for the form of the MH fix; and to 
>> Tobias Hartmann for the C1 fix. Their help was very much appreciated (and 
>> needed!).
>> tl;dr version: there are some places where badly formed interface method 
>> calls (which are not detected by the verifier) were missing runtime checks 
>> on the type of the receiver. Similar issues have been fixed in the past and 
>> this was a remaining hole in relation to invokespecial semantics and 
>> interface calls via MethodHandles. It also turned out there was an issue in 
>> C1 that affected direct invokespecial calls.
>> Description of changes:
>> - src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
>> Added a new form LF_INVSPECIAL_IFC for invokespecial of interface methods.
>> - src/java.base/share/classes/java/lang/invoke/MethodHandles.java
>> Renamed callerClass parameter to boundCallerClass, where it originates from 
>> findBoundCallerClass. The name "callerClass" is misleading because most of 
>> the time it is NULL!
>> In getDirectMethodCommon, pass the actual caller class (lookupClass) to 
>> DirectMethodHandle.make. And correct the comment about restrictReceiver.
>> - src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
>> DirectMethodHandle.make now takes a callerClass parameter (which may be 
>> null).
>> DirectMethodHandle make "receiver" parameter is renamed "refc" as it is not 
>> the receiver (it's the resolved type of the method holder ie REFC).
>> The Special subclass now takes a "checkClass" parameter which is either 
>> refc, or callerClass. This is what we will check the receiver against.
>> In preparedLambdaForm we switch from LF_INVSPECIAL to LF_INVSPECIAL_IFC if 
>> the target method is in an interface.
>> In makePreparedLambdaForm we augment the needsReceiverCheck test to include 
>> LF_INVSPECIAL_IFC. (So we will not be doing a new receiver type check on all 
>> invokespecials, just those involving interface methods.)
>> Added DMH.checkReceiver which is overridden by both the Special and 
>> Interface subclasses.
>> - src/hotspot/share/c1/c1_Canonicalizer.cpp
>> Don't optimize away the checkcast when it is an invokespecial receiver check.
>> - test/jdk/java/lang/invoke/SpecialInterfaceCall.java
>> (I've moved this test back and forth between hotspot/runtime and j.l.invoke 
>> as it spans direct calls and MH calls. But I think on balance it lands 
>> better here.)
>> The test sets up direct interface method calls for which invokespecial is 
>> generated by javac, and similarly it creates MethodHandles with 
>> invokespecial semantics. The should-not-throw cases are trivial. The 
>> should-throw cases involve MH wizardry.
>> The test is broken into three parts to check the behaviour on first use 
>> (when the method has to be initially resolved); on second use (to test we 
>> don't use the cpcache in a way that is invalid); and again after forcing JIT 
>> compilation of the calls.
>> The test is run 5 times to exercise the interpreter (yes the multiple runs 
>> internal to the test are redundant in this case, but it's much simpler to 
>> just run it all than try to work out what needs to be run); the three 
>> variants of using C1, plus a C2 only run.
>> ---
>> Testing:
>>   - the new test of course
>>   - hotspot/runtime/*
>>   - hotspot/compiler/jsr292
>>   - jdk/java/lang/invoke
>>   - hs tiers 1 and 2
>>   - jdk tiers 1, 2 and 3
>> Plus some related closed tests.
>> Thanks,
>> David
>> -----

Reply via email to