<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From: </b>"Dan Heidinga" <heidinga@redhat.com><br><b>To: </b>"Remi Forax" <forax@univ-mlv.fr><br><b>Cc: </b>"John Rose" <john.r.rose@oracle.com>, "valhalla-spec-experts" <valhalla-spec-experts@openjdk.java.net><br><b>Sent: </b>Monday, August 14, 2023 4:35:31 PM<br><b>Subject: </b>Re: Target of opportunity: remove method <vnew> and aconst_init / withfield opcodes<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 14, 2023 at 9:55 AM <<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)"><br><br><hr id="m_-7040534972739053525zwchr"><div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><b>From: </b>"Dan Heidinga" <<a href="mailto:heidinga@redhat.com" target="_blank">heidinga@redhat.com</a>><br><b>To: </b>"John Rose" <<a href="mailto:john.r.rose@oracle.com" target="_blank">john.r.rose@oracle.com</a>><br><b>Cc: </b>"Remi Forax" <<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>>, "valhalla-spec-experts" <<a href="mailto:valhalla-spec-experts@openjdk.java.net" target="_blank">valhalla-spec-experts@openjdk.java.net</a>><br><b>Sent: </b>Monday, August 14, 2023 2:53:31 PM<br><b>Subject: </b>Re: Target of opportunity: remove method <vnew> and aconst_init / withfield opcodes<br></blockquote></div><div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><div dir="ltr">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.<br><div>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. </div><br><div>Old bytecode:</div><div>Point changeX(int x) {</div><div>  aload0</div><div>  iload_1</div><div>  withfield "Point:x"</div><div>  areturn</div><div>}</div><br><div>What would the new bytecode do?</div></div></blockquote><br><div>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.<br></div><br><div>The constructor of Point<br></div><div>  <init>(int x, int y) {<br></div><div>    aload 0<br></div><div>    iload 1<br></div><div>    putfield Field:x<br></div><div>    aload 0<br></div><div>    iload 2<br></div><div>    putfield Field:y<br></div><div>    return<br></div><div>  }  // here, 'this' is not larval anymore<br></div><br><div>For all the other methods, a value class or an identity class use the same bytecode, for the method Point:changeX<br></div><div>  Point changeX(int x) {</div><div>    new. // in larval state<br></div><div>    dup<br></div><div>    iload 1<br></div><div>    aload 0<br></div><div>    getfield Field:y<br></div><div>    invokespecial Method Point:<init>(II)V<br></div><div>    areturn // not larval anymore<br></div><div>  }<br></div></div></div></div></blockquote><br><div>If I'm following correctly, changing one field requires stacking all the fields and calling the constructor?  </div></div></div></blockquote><div><br></div><div>yes,<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_quote"><br><div>From a VM perspective withfield is nice but as I dig through my notes, I don't see any notes on how we'd expose it in the language.  All the examples I'm finding are either directly generating the withfield bytecode or java source that shows the fields passing through a constructor.  Do we have a model on how javac would generate withfield or have we already defaulted in the ctor model?</div></div></div></blockquote><div><br></div><div>Brian has proposed a syntax for records (as part of Amber) in the past<br data-mce-bogus="1"></div><div>  <a href="https://github.com/openjdk/amber-docs/blob/master/eg-drafts/reconstruction-records-and-classes.md">https://github.com/openjdk/amber-docs/blob/master/eg-drafts/reconstruction-records-and-classes.md</a></div><div>but there were no concensus about it.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>And the mapping for the compiler is not obvious given that withfield is limited to the nestmates of a value type.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>Currently the compiler only emits withfield (or aconst_init) inside a <vnew> method.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_quote"><br><div>--Dan</div></div></div></blockquote><div><br></div><div>Rémi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)"><div><div>  <br></div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><div dir="ltr"><br><div>--Dan</div></div></blockquote><br><div>Rémi<br></div><br><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Aug 12, 2023 at 6:49 PM John Rose <<a href="mailto:john.r.rose@oracle.com" target="_blank">john.r.rose@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">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. <br>
<br>
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. <br>
<br>
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. <br>
<br>
> On Aug 12, 2023, at 1:40 PM, Remi Forax <<a href="mailto:forax@univ-mlv.fr" target="_blank">forax@univ-mlv.fr</a>> wrote:<br>
> <br>
> John and I and several others had several interresting discussions yesterday about Valhalla,<br>
> one of them about the removal of <vnew> and aconst_init/withfield, something i've called in the past, solving the last mile issue.<br>
> <br>
> 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.<br>
> <br>
> 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.<br>
> <br>
> 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.<br>
> <br>
> 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.<br>
> <br>
> 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.<br>
> <br>
> 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 :)<br>
> <br>
> 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.<br>
> <br>
> regards,<br>
> Rémi<br>
</blockquote></div></blockquote></div></div></div></blockquote></div></div><br></blockquote></div></div></body></html>