Moving from VVT to the L-world value types (LWVT)

Frederic Parain frederic.parain at oracle.com
Wed Jan 24 20:24:26 UTC 2018


Karen,

Thank you for your careful review.
My answers are in-lined below and I’ve uploaded an updated version of the
document with the fixes:

http://cr.openjdk.java.net/~fparain/L-world/L-World-JVMS-2.pdf

> On Jan 24, 2018, at 14:32, Karen Kinnear <KAREN.KINNEAR at ORACLE.COM> wrote:
> 
> Frederic,
> 
> Many thanks for the JVMS rough draft, chart of bytecodes and what checking they need and
> the mismatch chart. They are extremely helpful.
> 
> Questions/comments on the JVMS: http://cr.openjdk.java.net/~fparain/L-world/L-World-JVMS-2.pdf
> 
> 2.4 
> In the paragraph that describes null related to references:
>   The null reference initially has no run-time type, but may be cast to any type
> (implies checkcast, instanceof will continue unchanged - which is our current proposal)
>   The default value of a reference type is null.
>      - Should that be the default value of an object class type is null?
> 
> Do we want to describe the default value of a value class type?
> Perhaps we can leave these changes for Dan.

The default value for the _reference_ type is null.
Which is different from the default value of an instance of a value class.
The content of the default value for value class is define with the
defaultvalue bytecode:
"All instance variables of the instance must have their default initial values (§2.3, §2.4)."

This a “pointer" vs “instance designed by the pointer” distinction.

But it could be confusing. I’m open to better suggestions.

> 
> 4.1/ 4.5
> From our discussion today, it sounds as though we can try Remi’s original/John’s proposal
> for just tracking knowledge of a value type in the class file at two places:
> 1) when declaring a class, the class access_flags would add ACC_VALUE_TYPE
> 2) when declaring a field, the field access_flags would add ACC_VALUE_TYPE
> (small note - can we use 0x100?)
> 

Fixed

> 
> 4.1 There is a comment that it is invalid to have ACC_INTERFACE and ACC_VALUE_TYPE
> I believe it should also be invalid to have ACC_ABSTRACT and ACC_VALUE_TYPE

Fixed

> 6 invoke special
>   Where do we throw an exception if we have an <init> method in a value class? Would that be verifier?
>   Just in case they skip verification, might it be worth throwing an exception if the resolved method is an 
> instance initialization method and the class is a value class - would that be an ICCE? or a NoSuchMethodError?
> 
This is a point we should discuss with the langtools team.
Today, even Valhalla Value Types have an <init> method because javac refuses to compile a
class with final fields that are not initialized in a constructor.
It makes sense to forbid the <init> method for value class, but there might be consequences
I cannot see yet.

> 
> 6 monitorenter
>   Run-time Exception:
>     “iff object ref” -> “if object ref”
>      “monitor exit throws a IllegalMonitorStateException” -> “monitorenter” (and “an” before vowel Illegal…)
> 
> 
Fixed

Thank you.

Fred


> 
>> On Jan 24, 2018, at 11:42 AM, Frederic Parain <frederic.parain at oracle.com> wrote:
>> 
>> Updated chart after Valhalla’s VM Meeting:
>> 
>> http://cr.openjdk.java.net/~fparain/L-world/ValueObjectMismatch-2.pdf
>> 
>> Fred
>> 
>>> On Jan 24, 2018, at 09:34, Frederic Parain <frederic.parain at oracle.com> wrote:
>>> 
>>> I’ve uploaded a quick summary of the potential issues that can be caused
>>> by a mismatch between the expected and the real nature of a class (object
>>> class or value class).
>>> 
>>> http://cr.openjdk.java.net/~fparain/L-world/ValueObjectMismatch-1.pdf
>>> 
>>> If some cases are missing or incorrect, please let me know.
>>> 
>>> Fred
>>> 
>>> 
>>>> On Jan 23, 2018, at 19:05, Frederic Parain <frederic.parain at oracle.com> wrote:
>>>> 
>>>> Updated JVMS document with a few fixes and the Q-descriptors
>>>> removed (this removal changed only 3 lines!):
>>>> 
>>>> http://cr.openjdk.java.net/~fparain/L-world/L-World-JVMS-2.pdf
>>>> 
>>>> No attribute to list value classes has been added yet, so there’s
>>>> currently some issues for the verification.
>>>> 
>>>> Fred
>>>> 
>>>>> On Jan 23, 2018, at 16:25, Frederic Parain <frederic.parain at oracle.com> wrote:
>>>>> 
>>>>> Hi John,
>>>>> 
>>>>> thank you for the detailed feedback.
>>>>> 
>>>>> The Q-descriptor is not a fundamental part of the proposal, it is just an unsatisfying
>>>>> way for class files to express their expectations regarding types they think are value
>>>>> class types (to differentiate them from object class types). Q-descriptors provide this
>>>>> information but have drawbacks like the signature matching issue.
>>>>> 
>>>>> Remi’s proposal is appealing because it avoids the signature matching issue.
>>>>> An attribute is not the most convenient data structure for the JVM, but we can
>>>>> record the information elsewhere in our meta-data. However, it seems more
>>>>> brittle because the attribute can easily omitted, unless we make it mandatory
>>>>> after a given class file format number, with a slightly different syntax where all
>>>>> classes named in the class files have to be listed, so it can be verified. For
>>>>> older class file format, the attribute would be absent and all classes are assumed
>>>>> to be object classes.
>>>>> 
>>>>> We had two brainstorming sessions. yesterday and this morning, trying to figure
>>>>> out what would be the consequences of having only L-descriptors, with class
>>>>> files having different assumptions regarding the real nature of a type (object class
>>>>> or value class), either in the case of VBC migration or simply because of separate
>>>>> compilation. Some issues are related to the calling/returning conventions for the
>>>>> JIT compiled code. Some others issues are related to the class loader constraints,
>>>>> and the fact that a class with the wrong assumption regarding the nature of a class
>>>>> might prevent the real class from being loaded. The case where a class expects
>>>>> a Value Based Class (object class type) and the class is in fact a migrated value
>>>>> class seems to be OK. The case where a class expects a value class, but the
>>>>> class loader loads an object class seems much more problematic to us.
>>>>> 
>>>>> Regarding the migration of value based classes, trying to prevent null references
>>>>> from leaking into migrated code seems to be a step to far. We reviewed the issue with
>>>>> Karen this morning, and it doesn’t seems too dangerous to only check for null
>>>>> when the reference is stored in a field or array expecting an instance of a value
>>>>> class.
>>>>> 
>>>>> Thank you,
>>>>> 
>>>>> Fred
>>>>> 
>>>>> 
>>>>>> On Jan 19, 2018, at 23:22, John Rose <john.r.rose at oracle.com> wrote:
>>>>>> 
>>>>>> On Jan 16, 2018, at 12:56 PM, Frederic Parain <frederic.parain at oracle.com> wrote:
>>>>>>> 
>>>>>>> Here’s an attempt to bootstrap the L-world exploration, where java.lang.Object
>>>>>>> is the top type of all value classes (as discussed during the November meetings
>>>>>>> in Burlington).
>>>>>> 
>>>>>> This is excellent work, Frederic; thank you.  I'm really hopeful that we
>>>>>> are on the right track.
>>>>>> 
>>>>>>> ...
>>>>>>> Here’s a quick summary of the changes with some consequences on the HotSpot code:
>>>>>>> - all v-bytecodes are removed except vdefault and vwithfield
>>>>>> 
>>>>>> At some point we may want to strip the v-prefix from those survivors.  No hurry.
>>>>>> 
>>>>>>> - all bytecodes operating on an object receiver are updated to support values as well,
>>>>>>> except putfield and new
>>>>>> 
>>>>>> Yep.
>>>>>> 
>>>>>>> - single carrier type for both instances of object classes and instances of value classes
>>>>>>> - this carrier type maps to the T_OBJECT BasicType
>>>>>>> - T_VALUETYPE still exists but its usage is limited (same purpose as T_ARRAY)
>>>>>> 
>>>>>> T_ARRAY can be a confusing source of bugs.  I've always wondered if it was worth it.
>>>>>> 
>>>>>>> - qtos TosState is removed
>>>>>>> - JNI: the jobject type can be used to carry either a reference to an object or an
>>>>>>>      array or a value. The type jvaluetype, sub-type of jobject, is used when only
>>>>>>>      a value class instance is expected
>>>>>>> - Q…; remains the way to encode value classes in signature (fields and methods)
>>>>>> 
>>>>>> I'd like to move towards an ACC_VALUE bit on both fields and classes.
>>>>>> Again, no hurry, but (as in my previous message) I'd like to retire Q-descriptors.
>>>>>> 
>>>>>>> - In the constant pool, the CONSTANT_CLASS_info entry type is used to store a
>>>>>>> symbolic reference to either an object class or a value class
>>>>>>> - the ;Q escape sequence is not used anymore in value class names
>>>>>>> 
>>>>>>> 
>>>>>>> One important point of this exercise is to ensure that the migration of Value Based Classes
>>>>>>> into Value Classes is possible, and doable with a reasonable complexity and costs. In addition
>>>>>>> to the JVMS update (and consistent with the JVMS modifications), here’s a set of proposals
>>>>>>> on how to deal with the VBC migration. 
>>>>>> 
>>>>>> I'm glad you are doing this analysis, not only because VBC migration is
>>>>>> a wonderful goal, but also because I think the same analysis is necessary
>>>>>> just to manage separate recompilation, even if we never decided to
>>>>>> migrate a single class.
>>>>>> 
>>>>>> In short, I see you are leaning hard on Q-descriptors, but I don't think
>>>>>> you are getting enough value out of them, and they cause serious
>>>>>> problems.  More comments below… 
>>>>>> 
>>>>>>> 
>>>>>>> Migration of Value Based Classes into Value Classes:
>>>>>>> - challenges:
>>>>>>> - signature mismatch
>>>>>> 
>>>>>> Goes away when/if we retire Q-descriptors!
>>>>>> 
>>>>>>> - null
>>>>>> 
>>>>>> Can be dealt with by assuming non-null and throwing dynamic NPEs
>>>>>> as needed where Q types are in play.  Also, we tolerate "polluting nulls"
>>>>>> along paths where the Q/R distinction is not available, even if (at some
>>>>>> point later on) we realize that it was a Q all along.  Eventually, the
>>>>>> polluting null will cause an NPE.
>>>>>> 
>>>>>> (In my view, the NPE should happen later than one might prefer if it were
>>>>>> a true coding error rather than a recompilation artifact.  Catching polluting
>>>>>> nulls early in the presence of recompilation requires too many heroics.)
>>>>>> 
>>>>>>> - change in behavior
>>>>>> 
>>>>>> Yes, that's the tricky part.
>>>>>> 
>>>>>>> - proposal for signature mismatch:
>>>>>>>  - with LWVT, value class types in signatures are using the Q…; format
>>>>>>>  - legacy code is using signature with L…; format (because VBC are object classes)
>>>>>>>  - methods will have two signatures:
>>>>>>>    - true signature, which could include Q…; elements 
>>>>>>>    - a L-ified signature where all Q…; elements are re-written with the L…; format
>>>>>>>    - method lookup still works by signature string comparisons
>>>>>>>    - the signature of the method being looked up will compared against both the
>>>>>>>      true and the L-ified signatures, if the looked up signature matches the L-ified
>>>>>>>      signature but not the true signature, it means a situation where legacy code
>>>>>>>      is trying to invoke migrated code has been detected, and additional work might
>>>>>>>      be required for the invocation (actions to be taken have to be defined)
>>>>>>>   - signature mismatch can also occur for fields, this is still being investigating, the
>>>>>>>     proposal will be updated as soon as we have a solution ready to be published
>>>>>> 
>>>>>> This sort of thing is, for me, a rich argument against keeping Q-descriptors.
>>>>>> 
>>>>>>> - proposal for null references leaking to migrated code
>>>>>>> - having a null reference for a Value Based Class variable or field is valid in legacy code
>>>>>>>   but it becomes invalid when the Value Based Class has been migrated to a Value Class
>>>>>>> - trying to prevent all references with a value class type to get a null value would be very
>>>>>>>   expensive (it would require to look at the stackmap for each assignment to a local variable)
>>>>>> 
>>>>>> Yes.  We have to tolerate polluting nulls where the Q/R distinction is unavailable.
>>>>>> 
>>>>>>> -  the proposed solution is to allow null references for local variable and expression stack slots,
>>>>>>>   but forbid them for fields or array elements (bytecodes operating on fields and array have to
>>>>>>>   be updated to throw a NPE whenever a null reference is provided instead of a value class
>>>>>>>   instance)
>>>>>> 
>>>>>> Yes, I think this is on the right track.  On paths where a Q-type is needed
>>>>>> we do a null check.  That's the Java way.
>>>>>> 
>>>>>>> - null references are likely to be an issue for JIT optimizations like passing values in registers
>>>>>>>  when a method is invoked. The proposed solution is to only allow null references for value classes
>>>>>>>  in legacy code, by detecting them and blocking them when leaking to migrated code. The
>>>>>>>  detection can be done at invocation time, when a mismatch between the signature expected
>>>>>>> by the caller and the real signature of the callee is detected (see signature mismatch proposal above)
>>>>>> 
>>>>>> At some point, a polluting null might reach code that "knows" there is a Q type
>>>>>> (and may even "know" that it goes in an xmm register).  That's the point where
>>>>>> an NPE should be thrown.  In some cases, a deopt might be appropriate, to
>>>>>> correctly order the NPE by executing interpreter code.
>>>>>> 
>>>>>> Note that this combination of techniques does not Q-descriptors.  The lack
>>>>>> of Q-descriptors doesn't totally destroy the Q/R distinction; it just means you
>>>>>> have to execute a little further before you get to code which "knows" that
>>>>>> the null is illegal.
>>>>>> 
>>>>>>> - the null reference should also be detected and blocked when it is used as a return value and the
>>>>>>> type of the value to be returned is a value class type 
>>>>>> 
>>>>>> Doing this requires (a) Q-descriptors in method returns, (b) Remi's
>>>>>> ValueTypes table, or (c) toleration of nulls in the interpreter.  (The JIT
>>>>>> doesn't have to tolerate nulls:  It can deopt if it hits a surprise null,
>>>>>> or perhaps throw an early NPE.)  So, I am arguing for (c).
>>>>>> 
>>>>>>> In addition to the JVMS update, here’s a chart trying to summarize the new checks that will have to
>>>>>>> be added to existing bytecode when moving the vbytecodes semantic in to a* bytecodes. The categories
>>>>>>> in the chart are not very precise, but we can use it as a starting point for our discussions. The chart
>>>>>>> can also help defining which experiments could be done to estimate the costs of the different additional
>>>>>>> checks needed to be added to existing bytecodes.
>>>>>> 
>>>>>> The chart is really helpful, thanks.  More comments later.
>>>>>> 
>>>>>> Onward!
>>>>>> 
>>>>>> — John
>>>>>> 
>>>>>> 
>>>>> 
>>>> 
>>> 
>> 
> 



More information about the valhalla-dev mailing list