Target of opportunity: remove method <vnew> and aconst_init / withfield opcodes
forax at univ-mlv.fr
forax at univ-mlv.fr
Mon Aug 14 13:55:43 UTC 2023
> From: "Dan Heidinga" <heidinga at redhat.com>
> To: "John Rose" <john.r.rose at oracle.com>
> Cc: "Remi Forax" <forax at univ-mlv.fr>, "valhalla-spec-experts"
> <valhalla-spec-experts at openjdk.java.net>
> Sent: Monday, August 14, 2023 2:53:31 PM
> Subject: Re: Target of opportunity: remove method <vnew> and aconst_init /
> withfield opcodes
> Can one of you sketch out the bytecode sequences being proposed? Being able to
> look at some concrete "before we used <vnew>/aconst_init/withfield" and now "we
> use ....." comparisons would make the proposal clearer.
> For a value class like Point, with a "Point changeX(int x)" method, we used
> withfield to pop an instance off the stack, create a new instance with the
> updated single field, and put that instance back on the stack which allows us
> to preserve our immutability without needing a constructor per field we want to
> change.
> Old bytecode:
> Point changeX(int x) {
> aload0
> iload_1
> withfield "Point:x"
> areturn
> }
> What would the new bytecode do?
Sure, for the content of the constructor of a value class the bytecode is almost the same as for an identity class, the only difference is that the call to super() is not emitted.
The constructor of Point
<init>(int x, int y) {
aload 0
iload 1
putfield Field:x
aload 0
iload 2
putfield Field:y
return
} // here, 'this' is not larval anymore
For all the other methods, a value class or an identity class use the same bytecode, for the method Point:changeX
Point changeX(int x) {
new. // in larval state
dup
iload 1
aload 0
getfield Field:y
invokespecial Method Point:<init>(II)V
areturn // not larval anymore
}
> --Dan
Rémi
> On Sat, Aug 12, 2023 at 6:49 PM John Rose < [ mailto:john.r.rose at oracle.com |
> john.r.rose at oracle.com ] > wrote:
>> The header bit is not a problem because value object headers have no object
>> monitor. Thus, their headers are relatively empty OC state. Lots of slack.
>> In the spirit of minimizing JVMS changes I think this approa), might make sense.
>> The new byte codes paired well with new Q-descriptors and new verifier rules.
>> Not so much now.
>> Also, we already built the necessary states for serialization. The verifier will
>> also hide them for us in bytecode. That was a new discovery yesterday over
>> burgers.
>>> On Aug 12, 2023, at 1:40 PM, Remi Forax < [ mailto:forax at univ-mlv.fr |
>> > forax at univ-mlv.fr ] > wrote:
>>> John and I and several others had several interresting discussions yesterday
>> > about Valhalla,
>>> one of them about the removal of <vnew> and aconst_init/withfield, something
>> > i've called in the past, solving the last mile issue.
>>> Currently, refactoring from/to a value class/identity class is not a backward
>>> compatible move because of the way value classes are initialized using the
>>> <vnew> factory method. The reason is that during the initialization, a class
>>> instance is mutable but the VM considers that all value class instances are
>> > non-mutable.
>>> But at the same time, in order to implement Serialization of value classes
>>> (exactly de-serialization), there is a need for a mechanism to tag value class
>>> instances as "not yet finished to be initialized", something John refers has
>>> the object being in larval state because the de-serialization first create the
>>> instance and then populate its fields. In the lw prototypes, this is currently
>> > implemented using Unsafe.
>>> I think we have the opportunity now to use the same larval protocol for all
>>> values classes, making them binary backward compatible with identity classes.
>>> With both of them using the initialization protocol, the same
>> > new/dup/invokespecial dance.
>>> In term of specification, the idea is that "new" on a value class creates a
>>> larval instance and the end of the constructor mark the instance as
>> > non-larval/true-value-instance.
>>> I think that using the same initialization protocol at callsite is a good idea.
>>> We are re-aligning the bytecode with the Java code, One thing wichh is
>>> currently hard to understand for our users is that currently the Java code is
>>> the same for a value class and an identity class but the generated bytecode is
>>> not binary compatible. This also go well with the recent move to remove the
>>> Q-descriptor, we are moving toward the goal of being fully binary backward
>> > compatible.
>>> We may want to modify the verifier to verify that "this" does not escape the
>>> constructor in case of a value class, but I do not thing it's a requirement, so
>> > it's maybe better to not do that :)
>>> The end of constructor is already a point where all VMs/JITs are able to emit
>>> codes (for store/store barrier or finalizer registration), so we are piggy
>>> backing on an existing concept. The only main drawback I see is that the header
>>> of a buffered value type has to have one bit to indicate the larval state and
>> > those header bits are really precious.
>> > regards,
>> > Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-observers/attachments/20230814/fa393413/attachment-0001.htm>
More information about the valhalla-spec-observers
mailing list