[External] : Re: Consolidating the user model
Brian Goetz
brian.goetz at oracle.com
Thu Nov 4 14:56:27 UTC 2021
On 11/4/2021 2:54 AM, Kevin Bourrillion wrote:
>
>
> Point.ref pr = pv; // same object… now it’s on the heap, though,
> with a real live heap header
> assert pr.getClass() == Point.class; // same class, but...
>
>
> Why would we even want this? It would be very surprising/puzzling to me.
It's surprising because we're so used to "boxes" being a thing. But
let's look at this a bit.
int n = 3;
Object asObject = n;
People like that this compiles, and are not forced to say
`Integer.valueOf(3)`, but autoboxing hides something bad about boxing;
that the box type is something completely different. If we weren't so
steeped in the Culture of Boxing, we'd be surprised that a lowly
assignment like this changes the type and representation so drastically
(and as it turns out, unnecessarily.)
Let's compare with what happens with String.
String aString = new String("foo");
Object asObj = aString;
This code makes use of both String and Object, but in slightly different
and overlapping ways. String in this example is both a static and
dynamic type. When we make a new String with the String constructor, we
are instantiating a new instance whose dynamic type (getClass) is
String. Then we assign it to a variable whose static type is String.
When we then assign that variable to a new variable whose static type is
Object, nothing is being converted into an Object; the thing in asObj is
still a String; it's just held in a variable whose *static* type is a
supertype of String.
But, this isn't a perfect example, because Object is also a dynamic
type; I can create new Objects with an Object constructor. So let's
replace with Comparable:
String aString = new String("foo");
Comparable c = aString;
Now, String is both a static and dynamic type, but Comparable is *only a
static type*. There are no objects whose report their type as
Comparable; there are only objects whose type extends Comparable.
Now, let's go back to the integer example. The assignment here (in the
current language) takes the primitive value stored in n, and creates a
whole new, accidental object whose type is different from int. The only
saving grace is that you cannot discern the type of int, since you can't
ask it getClass, but we all know that boxing is a big seam in the
language, runtime, and reflection.
In the new world, Point.ref is like Comparable; it exists as a static
type for variables, but there are no objects that are *instances* of
Point.ref, because its not a concrete type.
Point p = new Point(3, 4);
Point.ref asRef = p;
This is like the String to Comparable example; the new variable refers
to the same object, but through an alias that has a different static type.
Now, alias is a funny word to use here, but this connects back to the
whole point of Valhalla -- the reason we disavow identity is that we are
no longer constrained to track the fact that two references were
initially assigned from the same object instance. In the absence of
identity, we're free to copy the state rather than the reference, which
admits powerful optimizations. But in the Point example above, it
really makes sense to think of the Point.ref as a reference to the *same
instance* that is held by p.
More information about the valhalla-spec-observers
mailing list