B3, default values, and implicit initialization
Brian Goetz
brian.goetz at oracle.com
Thu Apr 20 22:27:12 UTC 2023
As I mentioned yesterday, the high order bit here is how we describe a
class whose (null-restricted) instances can tolerate (and possibly even
encourage) uninitialized use, just as the primitives do today. Ignoring
the surface syntax, what we really need is an evocative term for such a
class. This term has to be useful and evocative to multiple participants:
- The author of a class, who is making a decision about whether the
zero state represents a sensible default.
- The client of a class, who may exploit the fact that instances may
be safely used uninitialized, or who may want to reason about flattening.
- The specification / descriptive documents, which will need a way to
talk about "classes that are friendly to uninitialized use."
This concept is made more difficult because this property will only have
observable effects for variables with null-restricted types.
On 3/28/2023 3:13 PM, Brian Goetz wrote:
> The recent update of JEP 401 contained a number of refinements to the
> user model, specifically, separating the primitive/reference
> distinction into a number of smaller distinctions (e.g., nullable vs
> non-nullable, optional vs required construction.) Overall this has
> been a very positive step forward.
>
> We still have a need for the distinction between what we've been
> calling B2 and B3; JEP 401 currently frames that in terms of
> "construction is optional." This is a big step forward; indeed, the
> key difference between them is whether the class _needs_ the
> "variables start out as null, and all instances are created by
> constructors" protection, or whether it admits the lighter-weight
> initialization protocol of "there's a a standard zero value, null-free
> variables are initialized to that" that primitives enjoy today. (Note
> that B3 classes don't require this lighter protocol, they merely
> enable it, much as primitives all give you the option of boxing to get
> the full conservative initialization protocol.)
>
> The idea of framing this as "construction is optional" is a good one,
> but the expression of it proposed in JEP 401 feels "not quite there".
> In this note I'll propose an alternative presentation, but the main
> goal here is around terminology and user model rather than syntax (so
> please keep the syntax agitation to a reasonable level.)
>
> The key distinction between B2 and B3 is that B3 has a _default value_
> which the VM can summon at will. This enables non-nullable heap
> variables to be flattened, because we can initialize these the same
> way we initialize other fields and array elements. Further, that
> default value is highly constrained; it is a physical zero, the result
> of initializing all fields to their default value.
>
> Flattening is of course a goal, but it is not something that exists in
> the programming model -- its just an optimization. What exists in the
> programming model is the default value, and what this unlocks is the
> possibility for variables to be _implicitly initializated_.
> Reference-typed variables today are _explicitly initialized_;
> variables start out null and have to be initialized with a constructed
> value. A class with a default value has the option (opted in through
> null-exclusion) for its variables to be implicitly initialized, which,
> like primitives, means that they start out with a valid default value,
> and can be further assigned to.
>
> Framed this way, the Valhalla performance story simplifies to:
>
> - Give up identity, get flattening on the stack;
> - Further give up explicit initialization, get flattening for small
> objects on the heap;
> - Further give up atomicity, get flattening for larger objects on the
> heap.
>
> Giving up explicit initialization entails both the class opting out of
> explicit initialization, _and_ the variable opting out of nullity.
>
> The key new terminology that comes out of this is implicit vs explicit
> initialization.
>
>
> Syntactically, my preference is to indicate that the default value can
> be summoned by giving a value class a _default constructor_:
>
> value class Complex {
> public final double re, im;
>
> public default Complex();
> }
>
> A default constructor has no arguments, no body, no throws clause, and
> implicitly initializes all fields to their default values. Unlike
> identity classes, value classes don't get constructions implicitly; a
> value class must declare at least one constructor, default or
> otherwise. This replaces the idea of "optional constructor", which is
> a negative statement about construction ("but you don't have to call
> me"), with a more direct and positive statement that there is a
> _default constructor_ with the required properties.
>
> Note that this is similar to the existing concept of "default
> constructor", which you get for free in an identity class if you don't
> specify any constructors. It is possible we can unify these features
> (and also with constructors in "agnostic" abstract classes), but first
> let's work out what it would mean in value classes, and see if we like it.
>
> In this model, a B3 class is just a value class with a default
> constructor -> a default constructor means that you have the choice of
> implicit or explicit initialization -> non-nullity at the use site
> opts into implicit initialization -> B3! gets flattening (for small
> layouts.)
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-experts/attachments/20230420/f9eb1a94/attachment-0001.htm>
More information about the valhalla-spec-experts
mailing list