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

Frederic Parain frederic.parain at oracle.com
Mon Feb 12 16:32:49 UTC 2018


Srikanth,

Thank you very much for your feedback.
My answers are in-lined below.

> On Feb 12, 2018, at 05:57, Srikanth <srikanth.adayapalam at oracle.com> wrote:
> 
> 
> Hello Frederic,
> 
> Here is some feedback on "L-World-JVMS-3.pdf" - As far I can tell, this is the last document on which you expressly asked for feedback though on the cr.openjdk site, I see two later versions 4.pdf and 4a.pdf
> 
> (1) "The null reference initially has no run-time type, but may be cast to any type."
> Does the above mean that null be cast into a value type ? (I didn't see any changes made to checkcast)
> Javac at the moment disallows casts of null to a value type - (where statically discernible of course)
> Please advise if any change is required.

The current design allows null references for value types, as long as they are not stored
in a container (field or array) declared as flattenable. This is a significant change from
previous design. So, casting null to a value class type is now legal.

> 
> (2) Nit: Table 4.1-A is not ordered any longer by value of bit mask.

Fixed

> 
> (3) 4.3.2. Field Descriptors: 
> 
> "ValueTypeName represents a binary value class name encoded in internal
> form (\(§4.2.1)."
> 
> The sentence above is the only reference to ValueTypeName in the document. So looks like a dangling reference that needs to be purged ??

It was a leftover from a previous version. I’ve removed it.

> 
> (4) 5.3.5:  .... 5. If C has any non-static field with the ACC_VALUE_TYPE flag set ...
> 
> I think this should be ACC_NON_NULLABLE ??

Yes. But this paragraph has been re-written in newer version.

> 
> (5) defaultvalue
> 
> Nit: An valueref => A valueref

Fixed

> 
> (6) withfield Forms:
> 
> vwithtfield = 204 (0xcc)
> 
> Nit: misspelt opcode.

Fixed

> 
> (7) withfield operation description says: "Return an instance of a value class with an updated instance field.". In the erstwhile VVT draft spec vwithfield's description reads: "Create a new value type instance by copying an existing value and modifying one of its instance fields." 
> 
> Does the present wording give the impression that value instances are mutable ? (although operand stack before and after calls it out as newvalueref and detailed description that follows makes it clear that a copy is made)

The previous wording “Create a new value” was too restrictive, because it forced to create a new value.
The new wording is less restrictive in order to allow more optimizations. For instance, if the reference to
the value class instance passed in argument to withfield is the only reference to this instance, a JVM can
decide to mutate this instance rather than creating a new instance, without altering the immutability of 
value classes. It would be equivalent to destroy the initial value and re-allocate a new one at the exact
same location. This new wording might also allow JVMs to use pre-allocated values in some cases.

However, you have a point that this new wording could be mis-leading. 

> 
> (8) withfield:
> 
> "which gives the name and descriptor of the field as well as a symbolic reference to the class in which the field is to be found. The class of valueref must not be an array nor an object class."
> 
> In the VVT spec, this used to be: "which gives the name and descriptor of the field as well as a symbolic reference to the value type in which the field is to be found."
> 
> 
> Is the VVT wording better ?? 

Updated to:

"which gives the name and descriptor of the field as well as a symbolic reference to the value class in which the field is to be found."

>  
> (9) withfield: 
> 
> "If the field is final, it must be declared in the
> current class, and the instruction must occur in an instance initialization method
> (<init>) of the current class (§2.9)."
> 
> (a) When can the updated field be non-final ?? I thought we are enforcing that all instance fields of a value type are final ??
> 
> (perhaps a copy paste problem ?)

Yes, copy-paste issue from original putfield specification. Removed.

> 
> (b) Presently javac treats a static method of a value type that is flagged with the modifier __ValueFactory
> (and whose return type is the same as the type of which the method is a member) as a privileged method that can apparently/seemingly modify a blank final instance field. It is lowered to withfield of course. This is also how it was in the VVT world. 
> 
> If any change is required in (b) I can do it. Do spell out what precisely is required.

For now, withfield remains a privileged operation which can only be performed by the value
class itself. We can continue to used the __ValueFactory marker as long as we do not have
a better support in the language.

However, I’m not seeing why the method must be a static method, it seems
reasonable to me to have a non-static method like this:
 
Value increment();

returning the next incremented value.

> 
> (10) withfield, Linking exceptions:
> 
> "The field must be final, it must be declared in the current value class, and the
> instruction must occur in a method of the current value class. Otherwise,
> an IllegalAccessError is thrown."
> 
> Per point made above, javac would emit withfield only from (a) static value factory method(s) and not any method of the current value class. 
> 

Thinking more about this, it might be time to drop __ValueFactory and allow
all methods from a value class to use withfield. I cannot remember the argument
in favor of stricter rules for this bytecode.

An updated version of the draft is now available here:
http://cr.openjdk.java.net/~fparain/L-world/L-World-JVMS-4b.pdf

Thank you this very useful feedback,

Fred


> 
>  
>  
> 
>  
> On Thursday 01 February 2018 12:38 AM, Frederic Parain wrote:
>> Here’s an update of the JVMS draft which includes the semantic
>> proposed below.
>> 
>> 
>> http://cr.openjdk.java.net/~fparain/L-world/L-World-JVMS-3.pdf
>> 
>> 
>> Feedback and comments are welcome.
>> 
>> Fred
>> 
>> 
>> 
>>> On Jan 31, 2018, at 05:54, Remi Forax <forax at univ-mlv.fr>
>>>  wrote:
>>> 
>>> 
>>> 
>>> ----- 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