Moving from VVT to the L-world value types (LWVT)
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)
> 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.
I agree about the semantics,
the name of the flag is wrong, it should be ACC_FLAT_THUS_NON_NULLABLE :)
>> 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
>>> 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.
>>> 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.
> > — John
More information about the valhalla-dev