<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <div class="markdown-here-wrapper" data-md-url="" style="" markdown-here-wrapper-content-modified="true">
      <p style="margin: 0px 0px 1.2em !important;">On 14/03/2023 11:06,
        Alan Paxton wrote:</p>
      <p style="margin: 0px 0px 1.2em !important;"></p>
      <div class="markdown-here-exclude">
        <p></p>
        <blockquote type="cite" cite="mid:CAKBoMRmPm5deo9X3o6un=khEXAyEzDFB+wze8evb2udF2+Wmxw@mail.gmail.com">
          <div>You might be able to point me at something that explains
            what goes on under the cover of invocation, and why exact
            matters ? My overall takeaway is that there are a number of
            rules of thumb for making use of FFI fast, if you follow
            them you get equivalent performance to JNI, with safety for
            free.</div>
        </blockquote>
        <p></p>
      </div>
      <p style="margin: 0px 0px 1.2em !important;"></p>
      <p style="margin: 0px 0px 1.2em !important;">Hi Alan,</p>
      <p style="margin: 0px 0px 1.2em !important;">thanks for coming
        back to us - it’s great that you have been able to reproduce the
        results.</p>
      <p style="margin: 0px 0px 1.2em !important;">As for why “exact”
        matter - that has to do with the method handle machinery (upon
        which var handles are also built). Both VarHandle::get/set and
        MethodHandle::invokeXYZ are “polymorphic signature” methods.
        This means that the java static compiler will look at these
        calls, and emit a <em>specialized</em> method descriptor for
        the call. So, if you have:</p>
      <pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code class="hljs language-java" style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;display: block; overflow-x: auto; padding: 0.5em; color: rgb(51, 51, 51); background: rgb(248, 248, 248) none repeat scroll 0% 0%; -moz-text-size-adjust: none;">String s = (String)methodHandle.invokeExact(<span class="hljs-number" style="color: rgb(0, 128, 128);">10</span>);
</code></pre>
      <p style="margin: 0px 0px 1.2em !important;">The compiler will
        emit a descriptor for that call with type <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">(int)String</code>.
        (A similar thing happens for var handle calls).</p>
      <p style="margin: 0px 0px 1.2em !important;">Now, the “exact” bit
        has to do with whether the JVM can “trust” that the symbolic
        description emitted by javac is the same as the type of the
        invoked method handle. If that’s the case, we can go straight to
        the method handle, and most (all) of the method handle machinery
        goop disappears when the call is inlined.</p>
      <p style="margin: 0px 0px 1.2em !important;">If, however, we use
        an “inexact” call (e.g. MethodHandle::invoke), we are telling
        the JVM that it needs to be prepared to perform some adaptations
        - that is, the symbolic description might be different from the
        method handle type. For instance, our static descriptor might
        say:</p>
      <pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">(int)String
</code></pre>
      <p style="margin: 0px 0px 1.2em !important;">but our underlying
        method handle might be like this:</p>
      <pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">(Integer)String
</code></pre>
      <p style="margin: 0px 0px 1.2em !important;">Method handles allow
        these adaptation (boxing, and widening, mostly) by wrapping the
        target method handle in a so called “asType” adaptation. This
        returns a <em>new</em> method handle which has a signature that
        matches that of the incoming arguments, converts them to the
        right values, and then forwards them to the original method
        handle.</p>
      <p style="margin: 0px 0px 1.2em !important;">So, there’s one extra
        level of indirection and, worse, since the same method handle
        can be adapted to many different signatures (e.g. both <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">(int)String</code>
        and <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">(Object)int</code>
        are valid adaptation for <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">(Integer)String</code>),
        the method handle maintains a “type cache”, so that if we keep
        adapting the same method handle to the same type we end up
        creating another adapter method handle (as we already have one).
        This explains why type adaptation typically ends up hurting
        performance quite a bit (even though the JVM have come a long
        way to deal with those in the last few years :-) ).</p>
      <p style="margin: 0px 0px 1.2em !important;">(Sidebar: the Java 19
        FFM API, with its separation between MemorySegment,
        MemoryAddress and Addressable makes it really hard to write <i>exact</i>
        method handle invocations, as the downcall method handle type
        says Addressable, while the user will probably just have a
        MemorySegment. This means that, in order to have javac write the
        correct symbolic description, users should cast their segment to
        Addressable, which seems counterintuitive. This was one of the
        main reasons as to why in 20 we have simplified the API to
        remove the split between MemorySegment and MemoryAddress).<br>
      </p>
      <p style="margin: 0px 0px 1.2em !important;">Var handles work
        pretty much in the same way - except that, for var handles, we
        don’t have inexact and exact version of get/set (that would have
        resulted in way too many methods). Instead, the var handle will
        act as “exact” or “inexact” based on whether the symbolic
        description matches the var handle type. If you get the exact
        path, all is good, and no type adaptation is required. If you go
        the inexact path, then you go through some form of
        MethodHandle::asType, which ends up hurting performance.</p>
      <p style="margin: 0px 0px 1.2em !important;">Detecting performance
        issues due to lack of exact var handle invocation has been
        historically tricky. The “withInvokeExactBehavior” was added
        precisely to allow developers to “express their intentions” more
        clearly (kudos to Jorn!).</p>
      <p style="margin: 0px 0px 1.2em !important;">As for the need for <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">final</code>,
        the JVM can only truly apply maximum inlining of var handles and
        method handles if these are “true constants” - which, for the
        JVM this means <em>both</em> static <em>and</em> final.</p>
      <p style="margin: 0px 0px 1.2em !important;">Maurizio</p>
      <div title="MDH:PHA+PGJyPjwvcD48ZGl2IGNsYXNzPSJtb3otY2l0ZS1wcmVmaXgiPk9uIDE0LzAzLzIwMjMgMTE6MDYsIEFsYW4gUGF4dG9uIHdyb3RlOjxicj48L2Rpdj48YmxvY2txdW90ZSB0eXBlPSJjaXRlIiBj
aXRlPSJtaWQ6Q0FLQm9NUm1QbTVkZW85WDNvNnVuPWtoRVhBeUV6REZCK3d6ZThldmIydWRGMitX
bXh3QG1haWwuZ21haWwuY29tIj48ZGl2PllvdSBtaWdodCBiZSBhYmxlIHRvIHBvaW50IG1lIGF0
IHNvbWV0aGluZyB0aGF0IGV4cGxhaW5zIHdoYXQgZ29lcyAKb24gdW5kZXIgdGhlIGNvdmVyIG9m
IGludm9jYXRpb24sIGFuZCB3aHkgZXhhY3QgbWF0dGVycyA/IE15IG92ZXJhbGwgCnRha2Vhd2F5
IGlzIHRoYXQgdGhlcmUgYXJlIGEgbnVtYmVyIG9mIHJ1bGVzIG9mIHRodW1iIGZvciBtYWtpbmcg
dXNlIG9mIApGRkkgZmFzdCwgaWYgeW91IGZvbGxvdyB0aGVtIHlvdSBnZXQgZXF1aXZhbGVudCBw
ZXJmb3JtYW5jZSB0byBKTkksIHdpdGgKIHNhZmV0eSBmb3IgZnJlZS48L2Rpdj48L2Jsb2NrcXVv
dGU+SGkgQWxhbiw8YnI+PHA+dGhhbmtzIGZvciBjb21pbmcgYmFjayB0byB1cyAtIGl0J3MgZ3Jl
YXQgdGhhdCB5b3UgaGF2ZSBiZWVuIGFibGUgdG8gcmVwcm9kdWNlIHRoZSByZXN1bHRzLjwvcD48
cD5BcyBmb3Igd2h5ICJleGFjdCIgbWF0dGVyIC0gdGhhdCBoYXMgdG8gZG8gd2l0aCB0aGUgbWV0
aG9kIGhhbmRsZSBtYWNoaW5lcnkgKGZyb20gd2hpY2ggVmFySGFuZGxlIGlzIGJ1aWx0IGZyb20p
LiBCb3RoIFZhckhhbmRsZTo6Z2V0L3NldCBhbmQgTWV0aG9kSGFuZGxlOjppbnZva2VYWVogYXJl
ICJwb2x5bW9ycGhpYyBzaWduYXR1cmUiIG1ldGhvZHMuIFRoaXMgbWVhbnMgdGhhdCB0aGUgamF2
YSBzdGF0aWMgY29tcGlsZXIgd2lsbCBsb29rIGF0IHRoZXNlIGNhbGxzLCBhbmQgZW1pdCBhIF9z
cGVjaWFsaXplZF8gbWV0aG9kIGRlc2NyaXB0b3IgZm9yIHRoZSBjYWxsLiBTbywgaWYgeW91IGhh
dmU6PC9wPjxwPmBgYGphdmE8YnI+U3RyaW5nIHMgPSAoU3RyaW5nKW1ldGhvZEhhbmRsZS5pbnZv
a2VFeGFjdCgxMCk7PGJyPmBgYDwvcD48cD5UaGUgY29tcGlsZXIgd2lsbCBlbWl0IGEgZGVzY3Jp
cHRvciBmb3IgdGhhdCBjYWxsIHdpdGggdHlwZSBgKGludClTdHJpbmdgLiAoQSBzaW1pbGFyIHRo
aW5nIGhhcHBlbnMgZm9yIHZhciBoYW5kbGUgY2FsbHMpLjwvcD48cD5Ob3csIHRoZSAiZXhhY3Qi
IGJpdCBoYXMgdG8gZG8gd2l0aCB3aGV0aGVyIHRoZSBKVk0gY2FuICJ0cnVzdCIgdGhhdCB0aGUg
c3ltYm9saWMgZGVzY3JpcHRpb24gZW1pdHRlZCBieSBqYXZhYyBpcyB0aGUgc2FtZSBhcyB0aGUg
dHlwZSBvZiB0aGUgaW52b2tlZCBtZXRob2QgaGFuZGxlLiBJZiB0aGF0J3MgdGhlIGNhc2UsIHdl
IGNhbiBnbyBzdHJhaWdodCB0byB0aGUgY2FsbCwgYW5kIG1vc3QgKGFsbCkgb2YgdGhlIG1ldGhv
ZCBoYW5kbGUgbWFjaGluZXJ5IGdvb3AgZGlzYXBwZWFycyB3aGVuIHRoZSBjYWxsIGlzIGlubGlu
ZWQuPC9wPjxwPklmLCBob3dldmVyLCB3ZSB1c2UgYW4gImluZXhhY3QiIGNhbGwgKGUuZy4gTWV0
aG9kSGFuZGxlOjppbnZva2UpLCB3ZSBhcmUgdGVsbGluZyB0aGUgVk0gdGhhdCBpdCBuZWVkcyB0
byBiZSBwcmVwYXJlZCB0byBwZXJmb3JtIHNvbWUgYWRhcHRhdGlvbnMgLSB0aGF0IGlzLCB0aGUg
c3ltYm9saWMgZGVzY3JpcHRpb24mbmJzcDsgbWlnaHQgYmUgZGlmZmVyZW50IGZyb20gdGhlIG1l
dGhvZCBoYW5kbGUgdHlwZS4gRm9yIGluc3RhbmNlLCBvdXIgc3RhdGljIGRlc2NyaXB0b3IgbWln
aHQgc2F5OjwvcD48cD5gYGA8YnI+KGludClTdHJpbmc8YnI+YGBgPGJyPjwvcD48cD5idXQgb3Vy
IHVuZGVybHlpbmcgbWV0aG9kIGhhbmRsZSBtaWdodCBiZSBsaWtlIHRoaXM6PC9wPjxwPmBgYDxi
cj4oSW50ZWdlcilTdHJpbmc8YnI+YGBgPC9wPjxwPk1ldGhvZCBoYW5kbGVzIGFsbG93IHRoZXNl
IGFkYXB0YXRpb24gKGJveGluZywgYW5kIHdpZGVuaW5nLCBtb3N0bHkpIGJ5IHdyYXBwaW5nIHRo
ZSB0YXJnZXQgbWV0aG9kIGhhbmRsZSBpbiBhIHNvIGNhbGxlZCAiYXNUeXBlIiBhZGFwdGF0aW9u
LiBUaGlzIHJldHVybnMgYSBfbmV3XyBtZXRob2QgaGFuZGxlIHdoaWNoIGhhcyBhIHNpZ25hdHVy
ZSB0aGF0IG1hdGNoZXMgdGhhdCBvZiB0aGUgaW5jb21pbmcgYXJndW1lbnRzLCBjb252ZXJ0cyB0
aGVtIHRvIHRoZSByaWdodCB2YWx1ZXMsIGFuZCB0aGVuIGZvcndhcmRzIHRoZW0gdG8gdGhlIG9y
aWdpbmFsIG1ldGhvZCBoYW5kbGUuPGJyPjwvcD48cD5TbywgdGhlcmUncyBvbmUgZXh0cmEgbGV2
ZWwgb2YgaW5kaXJlY3Rpb24gYW5kLCB3b3JzZSwgc2luY2UgdGhlIHNhbWUgbWV0aG9kIGhhbmRs
ZSBjYW4gYmUgYWRhcHRlZCB0byBtYW55IGRpZmZlcmVudCBzaWduYXR1cmVzIChlLmcuIGJvdGgg
YChpbnQpU3RyaW5nYCBhbmQgYChPYmplY3QpaW50YCBhcmUgdmFsaWQgYWRhcHRhdGlvbiBmb3Ig
YChJbnRlZ2VyKVN0cmluZ2ApLCB0aGUgbWV0aG9kIGhhbmRsZSBtYWludGFpbnMgYSAidHlwZSBj
YWNoZSIsIHNvIHRoYXQgaWYgd2Uga2VlcCBhZGFwdGluZyB0aGUgc2FtZSBtZXRob2QgaGFuZGxl
IHRvIHRoZSBzYW1lIHR5cGUgd2UgZW5kIHVwIGNyZWF0aW5nIGFub3RoZXIgYWRhcHRlciBtZXRo
b2QgaGFuZGxlIChhcyB3ZSBhbHJlYWR5IGhhdmUgb25lKS4gVGhpcyBleHBsYWlucyB3aHkgdHlw
ZSBhZGFwdGF0aW9uIHR5cGljYWxseSBlbmRzIHVwIGh1cnRpbmcgcGVyZm9ybWFuY2UgcXVpdGUg
YSBiaXQgKGV2ZW4gdGhvdWdoIHRoZSBKVk0gaGF2ZSBjb21lIGEgbG9uZyB3YXkgdG8gZGVhbCB3
aXRoIHRob3NlIGluIHRoZSBsYXN0IGZldyB5ZWFycyA6LSkgKS48YnI+PC9wPjxwPlZhciBoYW5k
bGVzIHdvcmsgcHJldHR5IG11Y2ggaW4gdGhlIHNhbWUgd2F5IC0gZXhjZXB0IHRoYXQgZm9yIHZh
ciBoYW5kbGVzIHdlIGRvbid0IGhhdmUgaW5leGFjdCBhbmQgZXhhY3QgdmVyc2lvbiBvZiBnZXQv
c2V0ICh0aGF0IHdvdWxkIGhhdmUgcmVzdWx0ZWQgaW4gdG9vIG1hbnkgbWV0aG9kcykuIEluc3Rl
YWQsIHRoZSB2YXIgaGFuZGxlIHdpbGwgYWN0IGFzICJleGFjdCIgb3IgImluZXhhY3QiIGJhc2Vk
IG9uIHdoZXRoZXIgdGhlIHN5bWJvbGljIGRlc2NyaXB0aW9uIG1hdGNoZXMgdGhlIHZhciBoYW5k
bGUgdHlwZS4gSWYgeW91IGdldCB0aGUgZXhhY3QgcGF0aCwgYWxsIGlzIGdvb2QsIGFuZCBubyB0
eXBlIGFkYXB0YXRpb24gaXMgcmVxdWlyZWQuIElmIHlvdSBnbyB0aGUgaW5leGFjdCBwYXRoLCB0
aGVuIHlvdSBnbyB0aHJvdWdoIHNvbWUgZm9ybSBvZiBNZXRob2RIYW5kbGU6OmFzVHlwZSwgd2hp
Y2ggZW5kcyB1cCBodXJ0aW5nIHBlcmZvcm1hbmNlLjwvcD48cD5EZXRlY3RpbmcgcGVyZm9ybWFu
Y2UgaXNzdWVzIGR1ZSB0byBsYWNrIG9mIGV4YWN0IHZhciBoYW5kbGUgaW52b2NhdGlvbiBoYXMg
YmVlbiBoaXN0b3JpY2FsbHkgdHJpY2t5LiBUaGUgIndpdGhJbnZva2VFeGFjdEJlaGF2aW9yIiB3
YXMgYWRkZWQgcHJlY2lzZWx5IHRvIGFsbG93IGRldmVsb3BlcnMgdG8gImV4cHJlc3MgdGhlaXIg
aW50ZW50aW9ucyIgbW9yZSBjbGVhcmx5LjwvcD48cD5BcyBmb3IgdGhlIG5lZWQgZm9yIGBmaW5h
bGAsIHRoZSBKVk0gY2FuIG9ubHkgdHJ1bHkgYXBwbHkgbWF4aW11bSBpbmxpbmluZyBvZiB2YXIg
aGFuZGxlcyBhbmQgbWV0aG9kIGhhbmRsZXMgaWYgdGhlc2UgYXJlICJ0cnVlIGNvbnN0YW50cyIg
LSB3aGljaCwgZm9yIHRoZSBKVk0gdGhpcyBtZWFucyBfYm90aF8gc3RhdGljIF9hbmRfIGZpbmFs
LjwvcD48cD5NYXVyaXppbzxicj48L3A+PHA+PGJyPjwvcD48cD48YnI+PC9wPjxwPjxicj48L3A+" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0;">​</div>
    </div>
  </body>
</html>