[lworld] Handling of missing ValueTypes attributes

Ioi Lam ioi.lam at oracle.com
Mon Jul 23 15:24:28 UTC 2018


I found two cases where the current repo doesn't generate ICCE as expected:

https://bugs.openjdk.java.net/browse/JDK-8208090
     [lworld] MethodHandle invocation should check for ValueType consistency

https://bugs.openjdk.java.net/browse/JDK-8207788
     [lworld] multinewarray bytecode should check for ValueType 
inconsistency

Thanks
- Ioi

On 7/11/18 12:42 PM, Karen Kinnear wrote:
> Ioi, Tobias,
>
> You asked a good question about MethodHandle and Reflection. I also 
> checked out JNI. This is my understanding - please correct me
> if my assumptions are inaccurate.
>
> Here are my assumptions about when we need value type consistency
> 1. verifier - mismatches between bytecodes and type (within a 
> classfile, no load/check for actual value type)
> 2. JIT performance optimizations
>     2a. flattening in containers - flattenable fields and array - 
> require check of value type vs. ACTUAL loaded type
>           - this is easy, we preload types
>
>     2b. JIT scalarization of field access - must be an ACTUAL value 
> type and must be flattenable
>        This will only work for fields that the JIT’d caller believes 
> are value types, the declarer believes are value types and the 
> declarer does an ACTUAL check
>        Need caller-callee agreement for a JIT’d caller.
>
>     2c. JIT calling convention - scalarization of arguments
>        Need either the caller-callee in agreement if both compiled OR
>        For caller calls by reference, adapter that can scalarize 
> arguments it knows are ACTUAL value types
>        Today adaptor is created at callee link time, so we explicitly 
> load types in local methods in the ValueTypes attribute so they can be 
> scalarized
>      2d. JIT returning a value type
>         I do not know our plans for value type return optimizations.
>         The adaptor for returns are stored off of the return type, so 
> they know the ACTUAL value.
>         In general we can check caller-callee consistency so we can be 
> in agreement about whether a type is a value type.
>         The exception is the JavaCalls::call_helper path used by 
> Reflection, jni (and others internally)
>             - I assume we will always return a reference here (I have 
> not studied the details yet, so I don’t know where that is handled)
> Details:
> 1. MethodHandles - invocation and field access always goes through 
> LinkResolver at this point.
> There are two exceptions here:
>     - one is when the MethodHandle creation does NOT pass in the 
> calling class information
>       - in that case there is no check for caller-callee consistency, 
> we need to look at this independently
>     - one is invokespecial indirect superclass (ACC_SUPER) which 
> performs selection in the java code.
>        - That is a rathole I won’t follow here - we should fix that 
> anyway - multiple potential approaches.
>
> 2. Reflection:
>    optimized reflection generates bytecodes, so goes through bytecode 
> path, so goes through LinkResolver.
>    initial reflection calls JavaCalls::call->JavaCalls::call_helper
>
> 3. JNI:
>    also goes through JavaCalls::call_helper
>
> JavaCalls::call_helper calls call_stub to invoke the entry_point which is:
>    normally: method->from_interpreted_entry
>    debug: method->interpreter_entry
>
> For argument passing, my assumption is that we are ok with the 
> JavaCalls::call_helper path because it always passes by reference
> and uses the callee adapter from interpreter which knows the declared 
> value types that can be scalarized. So the same adaptor that works for
> interpreted code works for call_helper where the caller always assumes 
> everything is a reference and passes by reference.
>
> JIT folks - does this work in practice?
>
> thanks,
> Karen
>
>
>
>> Thanks Karen for the explanation. I think it will simplify my patch 
>> for JDK-8206140 [lworld] Move return value null checks into the callee.
>>
>> If I understand correctly, this means that when we try to resolve a 
>> ClassRef, FieldRef, MethodRef, ..., in the constant pool, and there's 
>> a cross-class mismatch of ValueType, the constant pool entry will 
>> fail to resolve, and an ICCE will be thrown.
>>
>> This means the compiler should never see a mismatched cross-class 
>> reference. For example,
>>
>> class ClassB {
>>     void foo(Point p) {
>>          ClassA.m1(p);  // ....., invokestatic MethodRef #4 = 
>> ClassA.m1:"(LPoint;)V"
>>     }
>> }
>>
>> When foo is compiled, the compiler will see that the constant pool 
>> entry MethodRef #4 is unresolved. Thus, the compiler will generate an 
>> uncommon trap and let the interpreter handle it. The interpreter will 
>> try to resolve #4 again, resulting in an ICCE.
>>
>> BTW, value-types-consistency-checking-details.pdf doesn't mention 
>> MethodHandle and Reflection explicitly. However, I assume that the 
>> same set of rules applies as well?
>>
>> Thanks
>> - Ioi
>>
>>>  From an execution perspective, we would like to ensure that neither ClassC nor ClassA can get their hands on an instance of Point, so
>>> we are only passing null here. Tried to close all of these holes - could use review. Note to John - consistency checking for array elements
>>> relative to ValueTypes attribute is part of closing this hole, i.e. ensuring that a class that has the wrong information about whether a type
>>> is a value type can not get their hands on an instance of that value type.
>>>
>>> Does this make sense for LW1?
>>>
>>> thanks,
>>> Karen
>>>
>>> p.s. Frederic checked in round 1 of the consistency checking - but did not get round 2 in before he left for vacation. He is out this
>>> week and the next. I attached his patch out for review if you want to use it to test with to see if that helps the compiler. He will be back I
>>> believe the 23rd. I will check with Harold on Frederic’s verifier question - we may want to push this (without perhaps the new test) before
>>> he gets back so you can use it.
>>>
>>> Note - John asked for some refactoring - given how tight the time is before EA and the vacation schedule - that will be a postlw1 rfe.
>>>
>>>
>>>
>>>
>>>> On Jul 10, 2018, at 8:22 AM, Tobias Hartmann<tobias.hartmann at oracle.com>  wrote:
>>>>
>>>> Hi John,
>>>>
>>>> On 10.07.2018 02:08, John Rose wrote:
>>>>> On Jul 9, 2018, at 3:44 PM, Ioi Lam<ioi.lam at oracle.com>  wrote:
>>>>>> In that case, I think the program's output should be the same as if the ValueTypes attribute had been present, although performance may differ (slower, more heap allocations, etc).
>>>>>>
>>>>>> Is this understanding correct?
>>>>> Yes, that is correct.  This model is intended to make it easier for old-school classfiles
>>>>> to link to old types which have (over time) been upgraded to value types.
>>>> How do we then handle the following scenario?
>>>>
>>>> We have a method m1(MyValue vt) in a class that has no value types attribute set although MyValue is
>>>> a value type. Once the calling convention for that method is determined (i.e. at adapter creation),
>>>> we therefore don't know that MyValue is a value type and as a result, m1 will expect vt to be passed
>>>> as oop.
>>>>
>>>> Now another compiled method m2 that calls compiled m1 might be well aware that vt is a value type
>>>> but has no way to know that m1 does *not* expect vt to be passed as fields (especially if the call
>>>> is virtual).
>>>>
>>>> Thanks,
>>>> Tobias
>>
>




More information about the valhalla-dev mailing list