The Good Default Value

Brian Goetz brian.goetz at oracle.com
Thu Jun 1 22:41:59 UTC 2023


Saw this coming :)

On 6/1/2023 6:26 PM, Kevin Bourrillion wrote:
> There is one thing that I simply can never let go without comment 
> (which Brian had to have known :-)).
>
>
> On Wed, May 31, 2023 at 11:37 AM Brian Goetz <brian.goetz at oracle.com> 
> wrote:
>
>     ### Initialization
>
>     The key distinction between today's primitives and objects has to
>     do with
>     _initialization requirements_.   Primitives are designed to be _used
>     uninitialized_; if we declare a field `int count`, it is reliably
>     initialized to
>     zero by the JVM before any code can access it.  This initial value
>     is a
>     perfectly good default, and it is not a bug to read or even
>     increment this field
>     before it has been explicitly assigned a value by the program,
>     because it has
>     _already_ been initialized to a known good value by the JVM.  The
>     zero value
>     pre-written by the JVM is not just a safety net; it is actually
>     part of the
>     programming model that primitives start out life with "good
>     enough" defaults.
>     This is part of what it means to be a primitive type.
>
>
> Uninitialized values of primitive types do still cause bugs.

Another way to think about this is the historical progression.

In hardware / assembly language, when you load a value from a register 
or memory location, and you haven't provably put a good value there, you 
get an out-of-thin-air value.  There is no "safe initialization" of 
anything; there is just memory and registers.

C more or less propagates this approach; if you don't initialize a 
variable, you get what you get.  C doesn't force indirections on you; 
you have to ask for them.

Java 1.0 moved the ball forward for direct storage, saying that the 
initial value of any heap variable is zero, and requires that locals be 
initialized before use.  It also moves the ball forward by putting 
indirections in for you where they are semantically needed. But Java 
copies what C did for primitives; in the desire to not make arithmetic 
ungodly expensive, an int is just a direct machine int, like in C, with 
a frosting of bzero.

Valhalla gives us a choice: we can flatten more non-nullable things, or 
we can cheapen (somewhat) the things that use null as a initialization 
guard.  The good thing is that we can choose which we want as the 
situation warrants; the bad thing is we can make bad choices.

People will surely make bad choices to get the flattening benefits of 
B3, because, performance!  But this is not all that different from the 
other bad performance-overrotations that people make in Java every day, 
other than this one is new and so people will initially fall into it more.

> As far as I know, Valhalla could *maybe* still decide to require that 
> non-nullable variables of value-class types be initialized 
> explicitly. Maybe it would complicate migration too much, I'm not 
> sure. I know it would require one new feature:
>
> `new ValClass[100] (int i -> something())`

For fields, we can close the gap by doing null checks at constructor end 
(in the same place we emit memory barriers to support the final field 
initialization safety guarantees.)  The latter is voided when `this` 
escapes construction, and the former would be as well, but this seems a 
pragmatic choice which narrows the initially-null problem quite a bit 
for fields.  As you point out, arrays are harder, and it requires 
something much like what you suggest (which is also a useful feature in 
its own right.)  Note that none of this is needed for B3!, only for 
B1!/B2!.

> ... which, importantly, must compile to the optimal code (that never 
> actually loops) when `something()` is literally just a call to 
> ValClass's implicit constructor (or is otherwise the default value for 
> the type in question). In case `(i -> 
> MyImplicitlyConstructableType())` is the behavior you want, you'd be a 
> bit steamed to have to write it out. But just *how* valuable is 
> getting to skip it? I wonder.

Nothing wrong with `new B3![n]`, any more than `new int[n]`.  It's B1/B2 
that have the problem.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-observers/attachments/20230601/c2c459d6/attachment-0001.htm>


More information about the valhalla-spec-observers mailing list