User model stacking: current status

Brian Goetz brian.goetz at oracle.com
Tue Jun 14 13:16:41 UTC 2022


> The val type for B2 should not exist at all

>
>     So B2 is really a B3a whose value projection is encapsulated. 
>
>
> and here you lost me, .ref and .val are supposed to be projection 
> types not classes, at runtime there is only one class.

And apparently I have to say this again .... It's fine to not understand 
what is being proposed.  If so, ask questions, or think about it for a 
few days before responding.  But it's Not OK to jump to dogmatic "should 
not" / "wrong" pronouncements before you understand what is being 
proposed.  That's just unhelpful.

>
>
>     Summary:
>
>         class B1 { }
>         value class B2 { private class val { } }
>         value class B3a { }
>         non-atomic value class B3n { }
>
>     Value class here is clearly the star of the show; all value
>     classes are treated uniformly (ref-default, have a val); some
>     value classes encapsulate the val type; some value classes further
>     relax the integrity requirements of instances on the heap, to get
>     better flattening and performance, when their semantics don't
>     require it.
>
>     It's an orthogonal choice whether the default is "val is private"
>     and "val is public". 
>
>
> It makes B2.val a reality, but B3 has no sane default value otherwise 
> it's a B3, so B2.val should not exist.
>

Let me try explaining again.

All value types have .ref and .val types.  They have the properties 
we've been discussing for a long time: ref types are references, and are 
therefore nullable and atomic; val types are direct values, are not 
nullable, and are _not necessarily_ atomic.

We've been describing B2 classes as those with "no good default", but 
that doesn't mean that they can't have a .val type.  It means we *can't 
trust arbitrary code to properly initialize a B2.val type.* Once 
initialized, B2.val is fine, and have the benefit of greater flatness.  
We explored language and VM features to ensure B2.val types are properly 
initialized, but that ran into the rocks.

But we can allow the B2 class itself to mediate access to the .val 
type.  This has two benefits:

  - We can get back some of the benefit of flattening B2.val types
  - Uniformity

Here are two examples of where a B2 class could safely and beneficially 
use B2.val:

      value class Rational {
           Rational[] harmonicSeq(int n) {
               Rational.val[] rs = new Rational.val[n];
               for (int i=0; i<n; i++)
                   rs[i] = new Rational(1, n);
               return rs;
           }
      }

Here, we've made a _flat_ array of Rational.val, properly initialized 
it, and returned it to the user.  THe user gets the benefit of flatness, 
but can't screw it up, because of the array store check.  If 
Rational.val were illegal, then no array of rationals could be flat.

Similarly, a nestmate could take advantage of packing:

     value class Complex {
         value class C3 {
             Complex.val x, y, z;

             ...
         }

         C3 c3(Complex x, Complex y, Complex z) { return new C3(x, y, z); }

     }

C3 gets the benefit of full flattening, which it can do because its in 
the nest; it can share the flattened instances safely with code outside 
the nest.

(Access control is powerful thing.)

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


More information about the valhalla-spec-observers mailing list