The last miles
John Rose
john.r.rose at oracle.com
Tue Aug 22 20:02:05 UTC 2023
On 22 Aug 2023, at 11:03, Dan Smith wrote:
…
>>> 4) I'm not sure the prohibition on 'super' calls is actually
>>> necessary.
>>
>> No, but it’s a move of economy. Defining the meaning of super for
>> values would be extra work. We could do that; I’d prefer not to.
>> Remember that super-constructors for values are already very special
>> animals: They must be empty in a special sense. Forbidding calls to
>> them seems like the clean move.
>
> The rule is that super constructors must be empty because we had no
> concept of mutable state to communicate changes from parent to child.
> But now that we have larval objects...
>
> Concretely, what if:
>
> - putfield is a verifier error on non-identity class types, it only
> works on uninitializedThis
Alternatively, we don’t need to touch the verifier if we use a dynamic
larval-bit check on putfield. I like that much better. The effect on
the language and T.S. is the same as a verifier rule.
Specifically, allow putfield (on a final field) throughout the <init>
of the same class, just as we do now. Add a dynamic check on putfield
that throws an error if the object has been frozen. The interpreter
creates the larval buffer with the “frozen” bit clear, and sets it
on
exit from the appropriate constructor. (Probably the larval state is
a distinct header pattern; I am speaking here of a logical frozen bit.)
> - as usual, every <init> method (for all kinds of classes) must do a
> super-<init> invokespecial (or this-<init>? still thinking about that)
If we keep the rules exactly as they are, then we can make putfield
safe for values like this:
- putfield dynamically asserts unfrozen (object header in larval
state)
- exit from any constructor (super or not) sets frozen bit if unfrozen
Both of these rules appeal to dynamic state, and so do not require
verifier changes.
For calls to a “this” constructor, the implication is that the
object is frozen (becomes a mature usable adult value) after
invokespecial V.<init> (V is the value class). For calls to a
“super” constructor, the implication is that the object is frozen
after invokespecial S.<init> (S is the super).
The freeze operation can be something simple, like this pseudocode:
if (this->header().is_in_larval_state())
this->set_header(this->klass()->adult_state());
Or a CAS could be used if there are GC threads lurking nearby.
The return instruction(s) of such a constructor can be “hacked” in
the interpreter to perform the freeze operation, as one of the many
steps performed by the interpreter when a stack frame is taken down.
> Then:
>
> - value objects get built bottom-to-top, with fields set before a
> super() call, and freedom to use 'this' afterwards
> - abstract classes can participate too, following the same code shape
> - identity classes (abstract and concrete) have a little more freedom,
> because they can follow the same pattern *or* set their fields after
> the super() call
Yes. All of these use cases can be made to work with zero verifier
changes.
If we do not forbid the super-<init> call — or even require it, as in
today’s verifier – then we need a way for the interpreter to execute
it.
Can we just allow today’s verifier and interpreter rules to “bang
away”
on the larval value? Maybe, if the first constructor return (including
Object.<init>) promotes the value to adult. This puts the burden on
the coder of values to push the <init> calls (including the whole
super chain) to the end of the method, after all putfields.
If this actually works, I suppose it would lead to an even simpler JVMS.
We might not need special markings for constructors of abstract supers.
> I need to think more about this, but it seems to me at the moment that
> everything falls out cleanly...
>
>>> (If it works, does this mean we get support for super fields "for
>>> free"?)
>>
>> That is probably true. Do we care?
>
> I'd be happy to get rid of special rules that have to do with super
> fields. (Replacing it with a rule that says certain shapes of abstract
> class constructors imply identity.) Not so much because of particular
> use cases, but because it makes the language more regular.
Let’s think about it, but also be willing to push this off to later,
at the cost of putting in special markings for abstract supers that are
value-capable.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-observers/attachments/20230822/096263c4/attachment-0001.htm>
More information about the valhalla-spec-observers
mailing list