On 2/8/2023 9:27 AM, Remi Forax wrote:
The goal is a general-purpose feature that
lets programmers express intent about nulls, and that is preserved at runtime
sufficiently for JVMs to observe that "not null" + "value class" + "non-atomic
(or compact) class" --> "maximally flattenable storage". There are no "value
types", and there is no direct control over flattenability.
I would say that "not null" + "zero default value class" is necessary for 
flattening.
Then "non-atomic class" can help, but there is no guarantee.

Layout decisions are the purview of the JVM; Valhalla's approach to flattening is to allow the user to influence flattening by selecting semantic properties that remove impediments to flattening.  An approximate rubric for "when will things flatten" (in the heap) is:

    type is identity-free
    && variable is null-free
    && (type layout is small || type is non-atomic and not huge)

There are other heroics the VM can do to get more flattening (e.g., using slack bits to represent nulls in certain types), but this is the basic idea.  And these are all either _semantic_ things the user controls (identity-freedom, nullity, atomicity (which equates to the lack of cross-field invariants)) or things that it is entirely reasonable for the VM to make layout decisions based on (e.g., don't flatten huge things).

The main challenge of Valhalla has been teasing apart the various concerns to get them down to fine-grained properties we're willing to ask users to incorporate into their programming.

- Nullness is generally enforced at run time, via cooperation between javac and
JVMs. Methods with null-free parameters can be expected to throw if a null is
passed in. Null-free storage should reject writes of nulls. (Details to be
worked out, but as a starting point, imagine 'Q'-typed storage for all types.
Writes reject nulls. Reads before any writes produce a default value, or if
none exists, throw.)
The last sentence worry me a little, we have types that does not have a default 
value ??

"Sensible defaults" has been a long-standing challenge.  The VM has a very, very strong bias towards the default state of memory being all zeroes.  It is convenient that this yields sensible defaults for our primitives (numeric zero) and references (null pointers). Nullable types have a good zero default: null.  "Well behaved" value types like Complex have a good zero default: zero.  But types like LocalDate are problematic: the zero maps to a sensible value, but its a terrible default.  So types like LocalDate, while they could admit some flattening (and get good flattening on the stack), need protection in the heap from uninitialized values, and so LocalDate wants to be nullable.

That is: if your zero default is bad, you need null as a default. This is one of the central reasons for having Bucket 2.  (Spoiler: I don't like bucket 2.)


Reply via email to