Consolidating the user model

John Rose john.r.rose at oracle.com
Tue Nov 2 21:54:17 UTC 2021


+100; great summary

> On Nov 2, 2021, at 2:18 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
> 
> which means that the `L*` types might work out here.   Stay tuned for more details.  

A footnote, FTR, about L*-descriptors, in case it doesn’t ring a bell.

Brian is referring here to the thing we have talked about several
years ago, of loosely coupling a side-record with an occurrence
of L-Foo that means “link like L-Foo, but load and adapt like Q-Foo”.
We went through some of these iterations even before we settled
on Q-descriptors; they are back again, but in a far more tractable
form we think.

L* is not a new descriptor, it’s just an L (so it links to plain L’s)
but some sort of star-like marking * (not really in the descriptor
string but a side channel!) alerts the JVM to do extra loading
and adapting.

So, one current vision of this side-channel is a very limited early
use of the “Type Restriction” mechanism, as mentioned in the
Parametric VM proposal and elsewhere.  The idea is that a type
L*-Foo would be TR-ed to itself (Foo.class) and since TR’s use
eager loading (of the content of the TR, not of the type it
applies to) the effect would be similar to a Q-Foo, but it
would still be spelled L-Foo.  To avoid implementation
burdens, the JVM would not accept any more “interesting”
TRs, until we need to build them out for specialized generics.
Or we’d just have a one-shot, purpose-built side channel
which smells like an infant sibling to an eventual real T.R.
feature.  A T.R. that really restricts a type (instead of
just asks the JVM to take a closer look a la Q-Foo) is a
much deeper implementation challenge, since it creates
possible failure points when restrictions are violated.
An L* cannot violate itself since the value set is the same.
This is why L* only works on the middle bucket.

L*-Foo (using TRs or any other side-channel) is not a perfect
substitute for Q-Foo, because the stars “rub off too easily”
to ensure rigid correspondence between callers and callee.
This means L*-based API linkage requires more speculation
and runtime checking, compared to Q-based API linkage.

Although it may seem odd, there are a number of practical
reasons to use L* in the middle bucket but Q in the left
bucket.  The left bucket needs two descriptors, so L/Q.
The middle bucket has just one class mirror, so either Q
or else a mix of L and L*, and it needs some story for
migration for a few of its citizens, so L* looks good
again (linking with legacy L with a dynamic mixup).

As Brian says, we may elect to use Q uniformly for the
middle bucket, and handle the migration problem
another way.  It would be good if we could decide
Q vs. L* for the middle bucket without co-solving
the migration problem.

Anyway, such smaller details are up in the air.  The
points in Brian’s message are the high-order bits, and
the stuff I’ve shared here is a footnote.  Please do give
the high-order bits your best attention.  It’s a really
good write-up.

— John


More information about the valhalla-spec-observers mailing list