Default value for date/time

John Rose john.r.rose at oracle.com
Wed May 9 17:43:02 UTC 2018


On May 8, 2018, at 7:18 PM, Vitaly Davidovich <vitalyd at gmail.com> wrote:
> 
> Microsoft actually considered allowing user-provided default ctors for structs for C# 6 (IIRC) but backed away for compatibility reasons.

I am not a C# expert, but to me this story sounds over-simplified.
Surely there were other reasons.  Anyway, *we* have other reasons.

> Java, however, doesn’t have that compatibility concern (yet).  What’s the reason to not allow user specified default construction for value types? Sure, it’ll be a performance “hit” but this is user opt-in.  But it would allow users to avoid a new class of bugs.


Why is the performance hit less important than the user convenience hit?

I see why someone would want to specify their own default value, but
I also see that there are many workarounds to a JVM-mandated default.

What's more, suppose we all agreed the performance hit was not a big deal.
There are still huge problems in the way, ones that will require not
straightforward implementation but research and experimentation to solve.

1. We have been zeroing our heap storage for 20 years.  We don't *know*
all the places in HotSpot that are relying on all-zero-bits as a valid first
state for heap values.  We would have to *find them all* to implement
non-zero default states.  That will take a while.  We would not only undo
some optimizations (which we might agree to) but also experience a bug
tail, which nobody would like.

2. After all that pain, it will *still* be possible to observe broken values.
It will be harder, but still possible.  The specialized initialization of value
types with non-zero defaults cannot occur until the value type is bootstrapped
and can run its own nullary constructor (or whatever other notation is
required to specify the default; pick one).  In practice that means the
<clinit> has already started to run.  (Or are we going to use ConstantValue
initializers?  More doable but restrictive.)  This means that we need load
barriers to avoid observing default values until the default value constructor
has had a chance to compose the canonical default value.  Or else we
will have puzzlers where two default values will compare as unequal.

3. Even if one class can manage to create a default value without
accidentally observing it before it's done, if you have many value classes
trying to do the same thing at the same time (during system bootstrap)
we will have to arrange that *all* the classes are able to create their
canonical default values before *any* of them can observe *any*
of the default values.  In practice there will be bootstrap loops that
will just fail or will leak uninitialized canonical defaults.  We've all
been places like this, with <clinit> circularities; we will be there again
when people create complicated interdependent uses of value
types with complex interdependent default constructors.

This is where you get when you seriously try to implement such
things.  With deep VM changes it's never a case of "oh, how hard
could it be, and don't worry about performance."  And there's
probably a fourth problem I haven't thought of, too, which would
only come out after months of effort.  This is a place I don't want
to explore until and unless we are absolutely forced to, and the
arguments in favor don't get me there.

HTH
— John


More information about the valhalla-dev mailing list