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

Frederic Parain frederic.parain at oracle.com
Mon Jan 29 19:31:56 UTC 2018


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.

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

> 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