Moving from VVT to the L-world value types (LWVT)
srikanth.adayapalam at oracle.com
Mon Feb 12 10:57:13 UTC 2018
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.
(2) Nit: Table 4.1-A is not ordered any longer by value of bit mask.
(3) 4.3.2. Field Descriptors:
"ValueTypeName represents a binary value class name encoded in internal
The sentence above is the only reference to ValueTypeName in the
document. So looks like a dangling reference that needs to be purged ??
(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 ??
Nit: An valueref => A valueref
(6) withfield Forms:
vwithtfield = 204 (0xcc)
Nit: misspelt opcode.
(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)
"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 typein which
the field is to be found."
Is the VVT wording better ??
"If the field is final, it must be declared in the
current class, and the instruction must occur in an instance
(<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 ?)
(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.
(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.
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.
> Feedback and comments are welcome.
>> 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)
>>> 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