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