Moving from VVT to the L-world value types (LWVT)
frederic.parain at oracle.com
Thu Jan 25 21:51:49 UTC 2018
> On Jan 24, 2018, at 16:53, John Rose <john.r.rose at oracle.com> wrote:
> On Jan 24, 2018, at 12:24 PM, Frederic Parain <frederic.parain at oracle.com> wrote:
>>> Do we want to describe the default value of a value class type?
>>> Perhaps we can leave these changes for Dan.
>> The default value for the _reference_ type is null.
>> Which is different from the default value of an instance of a value class.
>> The content of the default value for value class is define with the
>> defaultvalue bytecode:
>> "All instance variables of the instance must have their default initial values (§2.3, §2.4)."
>> This a “pointer" vs “instance designed by the pointer” distinction.
>> But it could be confusing. I’m open to better suggestions.
> Nullability is the confusing bit. Variables which are not primitives
> or flattened values are inherently nullable, and default to null,
> they are references. Even though their class is a value class.
> We are convincing ourselves that this is OK for variables which
> are JVM stack or local variables. It may also be true for fields,
> in some corner cases.
> Basically, if classfiles get out of sync, you can witness polluting
> nulls in variables which are not flattened. Including fields.
> We could restrict the confusing pollution if we could somehow
> ensure that field variables whose classes are value classes
> are *always* flattened, even if the class defining the field
> "forgot" to ask for the flattening. The practicalities of classfile
> evolution make this hard to enforce, so I think we are stuck
> with nullable value fields as a corner case: Exactly when
> the class "forgets" to say ACC_VALUE_TYPE.
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.
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.
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
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
-> reading the default value of this field (uninitialized)
returns the default value of its value class
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.
Bytecode quickening or JIT compilation will help avoiding the ACC_FLAT
test completely for cases 1 and 2-A.
> (BTW, maybe it should be ACC_FLAT. So a class defined
> as ACC_FLAT is a value class, and a field defined ACC_FLAT
> loads the field class and inlines that class's layout, if it's
> a value class. Flatness is a linked but distinct property of
> classes and fields.)
>>> 4.1/ 4.5
>>> From our discussion today, it sounds as though we can try Remi’s original/John’s proposal
>>> for just tracking knowledge of a value type in the class file at two places:
>>> 1) when declaring a class, the class access_flags would add ACC_VALUE_TYPE
>>> 2) when declaring a field, the field access_flags would add ACC_VALUE_TYPE
>>> (small note - can we use 0x100?)
>>> 6 invoke special
>>> Where do we throw an exception if we have an <init> method in a value class? Would that be verifier?
>>> Just in case they skip verification, might it be worth throwing an exception if the resolved method is an
>>> instance initialization method and the class is a value class - would that be an ICCE? or a NoSuchMethodError?
> Eventually we need to forbid object-style <init> methods in
> value classes, as a local structural constraint. We can be
> lax to start with, since such <init> methods will never run.
> Alternatively, we could allow value types to define <init>
> methods but require them to be static factories. That is,
> they must be ACC_STATIC and must return the value type.
> They must also have at least one parameter, since the
> nullary constructor should be reserved, to denote the
> default value.
> There's no advantage to this at the JVM level, compared
> with regular factory methods. But such a could provide
> a translation strategy for the value-type version of a
> "new" expression.
> var x = Complex<double>(0.0, -1.0);
> // invokestatic Complex<D>.<init>(DD)Complex<D>
>> This is a point we should discuss with the langtools team.
> Yes; if they want to repurpose <init>, we can do it. Or if they
> want to make a new token <make>, or some some standard
> string, it's up to them, I think.
>> Today, even Valhalla Value Types have an <init> method because javac refuses to compile a
>> class with final fields that are not initialized in a constructor.
> That's why we want to be lax today, until we can tighten
> up the rules.
>> It makes sense to forbid the <init> method for value class, but there might be consequences
>> I cannot see yet.
> I think it's safe to remove <init>. I suggest we *start* by
> removing <init>, and let the langtools people tell us what
> to put back in its place.
> — John
More information about the valhalla-dev