<html><body><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000"><div>Maurizio,<br data-mce-bogus="1"></div><div>This seems a good idea to separate the API in (1) and (2).<br></div><div>I think the BSM of (1) should return a MethodHandle instead of a CallSite and don't have a be real BSM but an API method that can be called by a BSM (see below).<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>There is still an issue with (2). As i understand you will have to extract the ingredients each time you call the BSM, so once for each toString/equals/hashCode instead of once for all of them.</div><div>To be able to share the extraction of the ingredients, the simplest way is to have a contstant dynamic that create an instance of the class that will contains the ingredient (i wonder if there is a bonus point to use a record class for that :) ) so the ingredients are extracted once and stored in an opaque object in the constant pool then each invokedynamic call inside toString/equals/hashCode can take that object as their argument.</div><div><br data-mce-bogus="1"></div><div>And for the trick to return a constant method handle because in the future maybe we will be able to use a MethodHandle instead of a ConstantCallSite + a MethodHandle,<br data-mce-bogus="1"></div><div>the BSM (2) should have a relaxed signature (return an Object) but the implementation doesn't have to support that now and when we will need it, it believe the best way to do that will be to document that in the future this BSM may return a MethodHandle instead of a CallSite so user code should be ready to deal with that.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>Rémi<br data-mce-bogus="1"></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>De: </b>"Maurizio Cimadamore" <maurizio.cimadamore@oracle.com><br><b>À: </b>"Chris Hegarty" <chris.hegarty@oracle.com><br><b>Cc: </b>"Remi Forax" <forax@univ-mlv.fr>, "amber-dev" <amber-dev@openjdk.java.net>, "compiler-dev" <compiler-dev@openjdk.java.net><br><b>Envoyé: </b>Mardi 22 Octobre 2019 12:01:47<br><b>Objet: </b>Re: RFR: JEP 359-Records: reflection code<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;"><p>Thinking more,<br>
I think the fundamental reason as to why the bootstrap method
leaves me not 100% convinced is that, on the one hand,
ObjectMethods tries hard to be a _general_ helper class, offering
a bootstrap method to compute equals/hashCode/toString on _all_
classes, not just records. And, I think, it is because of that
generality that the bootstrap method receives a bunch of getter
method handles - so that e.g. other language implementation can
still use these methods on regular POJOs.</p>
<p>But, if this is meant to be a general building block, then I
don't understand e.g. why we are unifying all the signatures. If a
client wants hashCode, I think it is kind of a design flaw that
(i) there's no such BSM with that name (the BSM is just called
"bootstrap") and (ii) that there still a requirement to pass a
'name list', which is ignored by the BSM.</p>
<p>So, the _general_ building block case seems to push for one BSM
per Object method, whereas the record translation use case seems
to push towards a single unified BSM.</p>
<p>I think we can actually have our cake and eat it too:</p>
<p>1) ObjectMethods could expose several BSMs - one for each Object
method, with the _right_ static argument list and names, to make
it easy for clients to find them. Of course, for generality, these
methods should be expressed in terms of MethodHandle[], since we
can't rely on the class being a record<br>
2) We coud add a j.l.Record.bootstrap, which, using core
reflection could extract the required ingredients, before
delegating to the _right_ BSM in ObjectMethods (e.g. the MH list
and the names list)<br>
</p>
<p>This way we get the best of both worlds: sharp BSMs for clients
that just want to implement object methods (which also works on
things that are not records); unified BSM which act as a record
translation target.<br>
</p>
<p>Maurizio<br>
</p>
<div class="moz-cite-prefix">On 22/10/2019 10:41, Chris Hegarty
wrote:<br>
</div>
<blockquote cite="mid:D7AA33E8-FF73-4D6C-A3AF-CBB94CE6D0BF@oracle.com">
<br class="">
<div><br class="">
<blockquote class="">
<div class="">On 22 Oct 2019, at 09:51, Maurizio Cimadamore
<<a href="mailto:maurizio.cimadamore@oracle.com" class="" target="_blank">maurizio.cimadamore@oracle.com</a>>
wrote:</div>
<br class="Apple-interchange-newline">
<div class=""><span style="caret-color: rgb(0, 0, 0);" class="">..</span><br class="">
<br style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none;" class="">
<span style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none; float: none; display: inline
!important;" class="">Let me rephrase. We have
Class::getRecordComponents; and we have
RecordComponent::accessor.</span><br style="caret-color:
rgb(0, 0, 0); font-family: Helvetica; font-size: 14px;
font-style: normal; font-variant-caps: normal;
font-weight: normal; letter-spacing: normal; text-align:
start; text-indent: 0px; text-transform: none;
white-space: normal; word-spacing: 0px;
-webkit-text-stroke-width: 0px; text-decoration: none;" class="">
<br style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none;" class="">
<span style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none; float: none; display: inline
!important;" class="">What is the need to pass _anything_
to the BSM, other than the record class (e.g. Point.class)
AND the method name (e.g. toString) ?</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica;
font-size: 14px; font-style: normal; font-variant-caps:
normal; font-weight: normal; letter-spacing: normal;
text-align: start; text-indent: 0px; text-transform: none;
white-space: normal; word-spacing: 0px;
-webkit-text-stroke-width: 0px; text-decoration: none;" class="">
<br style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none;" class="">
<span style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none; float: none; display: inline
!important;" class="">The BSM can take the .class, and get
the components; from there:</span><br style="caret-color:
rgb(0, 0, 0); font-family: Helvetica; font-size: 14px;
font-style: normal; font-variant-caps: normal;
font-weight: normal; letter-spacing: normal; text-align:
start; text-indent: 0px; text-transform: none;
white-space: normal; word-spacing: 0px;
-webkit-text-stroke-width: 0px; text-decoration: none;" class="">
<br style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none;" class="">
<span style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none; float: none; display: inline
!important;" class="">- you can easily derive names</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica;
font-size: 14px; font-style: normal; font-variant-caps:
normal; font-weight: normal; letter-spacing: normal;
text-align: start; text-indent: 0px; text-transform: none;
white-space: normal; word-spacing: 0px;
-webkit-text-stroke-width: 0px; text-decoration: none;" class="">
<span style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none; float: none; display: inline
!important;" class="">- you can also easily derive
accessor MHs (just a lookup away)</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica;
font-size: 14px; font-style: normal; font-variant-caps:
normal; font-weight: normal; letter-spacing: normal;
text-align: start; text-indent: 0px; text-transform: none;
white-space: normal; word-spacing: 0px;
-webkit-text-stroke-width: 0px; text-decoration: none;" class="">
<br style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none;" class="">
<span style="caret-color: rgb(0, 0, 0); font-family:
Helvetica; font-size: 14px; font-style: normal;
font-variant-caps: normal; font-weight: normal;
letter-spacing: normal; text-align: start; text-indent:
0px; text-transform: none; white-space: normal;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
text-decoration: none; float: none; display: inline
!important;" class="">I was _not_ advocating for
extracting a name from a direct method handle - that seems
brittle, given that the compiler implementation might
change, eventually. But doubling down on the reflection
API seems the right thing to do?</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica;
font-size: 14px; font-style: normal; font-variant-caps:
normal; font-weight: normal; letter-spacing: normal;
text-align: start; text-indent: 0px; text-transform: none;
white-space: normal; word-spacing: 0px;
-webkit-text-stroke-width: 0px; text-decoration: none;" class="">
</div>
</blockquote>
</div>
<br class="">
<div class="">A quick change shows that this simplifies the code a
lot ( since there is less arg checking )</div>
<div class=""><br class="">
</div>
<div class=""><a href="http://cr.openjdk.java.net/~chegar/records/ObjectMethods.00/" class="" target="_blank">http://cr.openjdk.java.net/~chegar/records/ObjectMethods.00/</a><br data-mce-bogus="1"></div>
<div class=""><br class="">
</div>
<div class="">Q: the TypeDescriptor arg can be used for linking a
dynamic constant. Is this still needed?</div>
<div class=""><br class="">
</div>
<div class="">-Chris.</div>
</blockquote><br></blockquote></div></div></body></html>