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

Remi Forax forax at univ-mlv.fr
Wed Jan 31 10:54:39 UTC 2018



----- Mail original -----
> De: "Frederic Parain" <frederic.parain at oracle.com>
> À: "John Rose" <john.r.rose at oracle.com>
> Cc: "valhalla-dev" <valhalla-dev at openjdk.java.net>
> Envoyé: Lundi 29 Janvier 2018 20:31:56
> Objet: Re: Moving from VVT to the L-world value types (LWVT)

> John,
> 
> Silently transforming null into the default value in case 2-B was
> just in case it could ease the handling of migrated case. If throwing
> NPE is OK here, it makes the semantic much cleaner. It also solves
> some problems we had while trying to add support for the null
> value in the value class’ equals() method.
> 
> During a brainstorming session with Karen this morning, we realized
> that case 2-A (ACC_FLAT flag set for an object class) should be in
> fact treated as an error, instead of just ignoring the flag.

Which means that changing a value type to a reference type is not a backward compatible change,
i'm Ok with that.

> 
> These two modifications makes the semantic mucho simpler and
> cleaner with only two cases: one where null is always valid, and
> one where null is never valid.
> 
> So here’s a re-write of the semantic:
> 
> Fields have a new access flag called ACC_NON_NULLABLE.
> 
> The type of a field with the ACC_NON_NULLABLE flag set must
> be a value class type, otherwise an ICCE is thrown.
> 
> 1 - If a field is declared without the ACC_NON_NULLABLE flag set:
>     - this field is initialized with the null reference
>     - it is valid to write null to this field
>     - note: JVMs are unlikely to flatten such field
> 
> 2 - If a field is declared with the ACC_NON_NULLABLE flag set:
>     - this field is initialized with the default value of this field’s value class
>     - writing null to this field causes a NPE
>     - JVMs are encouraged to flatten such field
> 
> This semantic makes much more sense because being non-nullable
> is a property of the container more than a property of the field’s type.
> 
> Fred

I agree about the semantics,
the name of the flag is wrong, it should be ACC_FLAT_THUS_NON_NULLABLE :)

Rémi

> 
>> On Jan 25, 2018, at 17:48, John Rose <john.r.rose at oracle.com> wrote:
>> 
>> On Jan 25, 2018, at 1:51 PM, Frederic Parain <frederic.parain at oracle.com> wrote:
>>> 
>>> Simply allowing non-flattened field to be null is not a viable
>>> solution because a consequence would be  that the result of
>>> reading  a non-initialized field would depend on wether or not
>>> the field has been flattened.
>> 
>> As you note below, it is possible to make the details
>> of null processing depend on whether the *field* was
>> declared flat or not.
>> 
>>> With Valhalla Value Types, we were able to use the null
>>> value internally for non-initialized non-flattened field because
>>> the JVM always knew if a field were a value type or not.
>> 
>> Nice trick.
>> 
>>> Unfortunately, this cannot be done in the L-world because
>>> when a non-initialized field is read, there’s no guarantee that
>>> the class of this field has been loaded yet.
>>> 
>>> So, here’s a proposal that provides a semantic for null value
>>> fields that do not depend on the implementation, and without
>>> additional runtime checks for non-value fields:
>>> 
>>> 1 - If a field is declared without the ACC_FLAT flag set:
>>>   -> it is never flattened (even if the class is already loaded
>>>      and it is a value class)
>>>   -> it is OK to write null on this field
>>>   -> reading the default value of this field returns null
>> 
>> Yes, that's what I had in mind too.
>> 
>>> 2 - If a field is declared wit the ACC_FLAT_flag set:
>>>   -> the class of this field is loaded before computing the layout
>>>      of the declaring class
>>>   A - If the field's class is an object class
>>>       -> same semantic as in 1 is applied
>> 
>> Yes.
>> 
>>>   B - If the field's class is a value class
>>>       -> writing null to this field results in setting this field
>>>          to the default value of its value class
>> 
>> We have a choice here:  We can also throw NPE on
>> such writes.  I think we should.  There's no legitimate
>> need for writing a null value to a flat field, I think.
>> 
>> (But maybe there's a translation strategy, that I'm not
>> noticing, that could use this behavior?)
>> 
>>>       -> reading the default value of this field (uninitialized)
>>>          returns the default value of its value class
>> 
>> If you can't write null w/o NPE, then the JVM can
>> still use the internal trick of allowing null as a
>> sentinel for the default value.
>> 
>>> Case 1 is the object world as we know it today, no changes, no
>>> additional runtime checks, values will be handled like objects.
>>> Case 2-A is the case where the ACC_FLAT has been mis-used
>>> on an object class.
>>> Case 2-B is the interesting value type case, and its semantic
>>> relies only on the presence of the ACC_FLAT flag, not on the
>>> decision of the JVM to flatten the field or not.
>> 
>> Exactly.
>> 
>>> Checks to intercept
>>> the null value are easy to implement, all information they need
>>> are in the field descriptor and on the execution stack.
>> 
>> I agree.  Resolving the CONSTANT_Fieldref to the descriptor
>> will determine whether the *field* was declared ACC_FLAT.
>> In that case null writes will fail and null reads (if any) can be
>> handled in some manner convenient to the JVM.
>> 
>>> Bytecode quickening or JIT compilation will help avoiding the ACC_FLAT
>>> test completely for cases 1 and 2-A.
>> 
>> Yes.
>> 
> > — John


More information about the valhalla-dev mailing list