<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>