Revised JEP: Null-Restricted Value Object Storage
Brian Goetz
brian.goetz at oracle.com
Tue Mar 21 19:14:43 UTC 2023
There's been a lot of change since the last update of this JEP, so let
me summarize the changes and the motivation. The current JEP text is
still very rough; the point of sharing it in this state is to sketch out
the next chunk of the story and how it connects to the other chunks,
even if they are not fully fleshed out.
#### Value and "primitive" classes
This JEP positions the Valhalla story as one of "the more flexibility
you give up, the better flattening you get." Identity classes get no
flattening. Value classes (B2) give up identity (but nothing else), and
they get better flattening on the stack (e.g., optimized calling
convention), but (absent VM heroics) no flattening on the heap. This is
already confusing to many users, because they hear "flattening" and
think "layout inlining."
To get heap flattening / layout inlining, you have to give up some
more. It took a while to figure this out, but we finally realized that
the key distinction between B2 and B3 has to do with its _initialization
protocol_ (or lack thereof). Non-nullability is important for
flattening, but it is secondary; before you can go non-nullable safely,
you have to obviate the need for null in the first place, which means
you need to make initialization optional.
We have nulls because most objects require initialization; simply
interpreting a block of zeroed memory as an instance of a class is
usually only incrementally worse than interpreting a block of garbage as
an instance of that class. To protect from interpreting uninitialized
memory as an object instance, object references use null as their
default value. The primitive types all share the characteristic that
the zero value is actually a good default, and therefore they do not
need the extra initialization safety afforded by object references and
null, and therefore they can be non-nullable, and therefore they can be
routinely flattened.
With this in mind, we downplay the distinction between B2 and B3; B3 is
a special kind of value class, one for which construction is optional
because the default (zero) value is considered good.
#### Performance story
The performance story becomes one of a spectrum of tradeoffs:
- Identity classes get lots of flexibility, but no flattening.
- Value classes give up identity, and get flattening on the stack
(optimized calling convention, reliable scalarization, etc), but no
flattening on the heap.
- Value classes that support default instances (B3) give up on the
requirement that all instances be initialized, and in return,
non-nullable variables can be flattened in the heap -- up to the limit
of atomic load/store operations.
- B3 classes that further opt out of atomicity can get heap flattening
for larger instances.
#### Ref, val, and bang
The previous version of the story divided uses of B3 classes into a
primitive type and a reference type, and there were a number of
properties that derived from the choice of reference vs primitive
(including nullability). We've now arrived at the point where we can
represent these properties individually, and therefore don't need to
appeal to this coarser ref-vs-val distinction. As a result, we can get
rid of the clunky X.ref / X.val notation, and express null-restriction
with the more familiar cardinality sigil, `X!`.
For purposes of this JEP, the use of null-restriction types is limited
to types where the null-restriction can be reified by the JVM (hello, Q
types); a separate JEP will explore extending it to all reference types
and the attendant consequences of erasure (e.g., null pollution.)
In this interpretation, we do not have to call `Point!` a primitive
type; we can call it a restriction of the reference type `Point`. (If
we do, we gain some uniformity for class types ("everything is a
reference"), at the expense of permanently living with a more visible
seam with primitives; we can continue to evaluate the tradeoffs here.)
On 3/21/2023 12:10 PM, Dan Smith wrote:
> I've updated JEP 401, formerly "Primitive Classes", now titled "Null-Restricted Value Object Storage". The purpose of this JEP is to allow for flattening of value objects in fields and arrays. This update gets there via two key features:
>
> - "Optional" constructors, which express the capability of a value class to have instances created outside the normal construction process.
>
> - Null-restricted types, which exclude null from the type's value set, and in the case of value classes with optional constructors, allow for a non-null default value.
>
> There's more to say about nullness, which is covered by its own JEP that we're still working on. But the idea of null-restricted variables is enough to unblock progress on value object flattening. (Eventually, we envision—at least for now—delivering the two JEPs at the same time.)
>
> The document is here:
>
> https://openjdk.org/jeps/401
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-experts/attachments/20230321/8656b56c/attachment.htm>
More information about the valhalla-spec-experts
mailing list