User model stacking: current status
Dan Heidinga
heidinga at redhat.com
Tue Jun 14 13:26:27 UTC 2022
On Tue, Jun 14, 2022 at 9:17 AM Brian Goetz <brian.goetz at oracle.com> wrote:
>
>
> 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.
And with Rational.val requiring atomic access, we can only flatten it
if the underlying HW supports it (in this case, 2 ints fits nicely in
64bits so we're good). Larger .val's can only be flattened if marked
as "non-atomic" (the B3n case). And because there's no tearing,
handing out the flattened Rational.val[] is safe.
Do I have that right?
--Dan
>
> 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.)
>
>
More information about the valhalla-spec-observers
mailing list