<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 10/07/2023 16:02,
        Brian S O’Neill wrote:</p>
      <blockquote style="margin: 1.2em 0px;border-left: 4px solid
        rgb(221, 221, 221); padding: 0px 1em; color: rgb(119, 119, 119);
        quotes: none;">
        <p style="margin: 0px 0px 1.2em !important;">I want to avoid
          polluting the other thread, which no longer has a<br>
          valid subject line anyhow…</p>
        <p style="margin: 0px 0px 1.2em !important;">1) The size limit
          of a memory segment is defined by a signed value,<br>
          thus limiting the address space to be 63-bit. Is it likely
          that all<br>
          64-bit architectures today and in the future only use the
          lower half<br>
          of the address range?</p>
      </blockquote>
      <p style="margin: 0px 0px 1.2em !important;">While it’s true that
        a memory segment can never be big enough as the full address
        space, in reality that limit is big enough - e.g. it is hard to
        imagine a developer wanting to express a region of memory whose
        size is bigger than 2^63. I believe the angle you are coming
        from here is that you want to use a memory segment to model the
        entire heap (at least judging from the other thread you
        started), and then wanting to just use a raw long pointer as an
        “offset” into the segment. Given the unsigned limitations, this
        will not work 100%: the FFM API specifies that the “long”
        argument you pass to MemorySegment::get (same for var handle) is
        a positive offset, relative to the start of the segment. That
        is, a negative offset is, by definition, <em>outside</em> the
        memory segment. So, I do not see a way to add support for full
        unsigned long as memory segment sizes/offsets - in fact, I
        believe that allowing negative values in places where we expect
        an offset is almost always a smell, and a place for bugs to
        hide.</p>
      <p style="margin: 0px 0px 1.2em !important;">In terms of
        interfacing with native code, note that the FFM API can still
        wrap whatever address a native library throws at it, by wrapping
        the base address (a long) into a segment using
        MemorySegment::ofAddress. This method takes a raw address value,
        which can be negative. Of course the size of the segment will be
        limited to “only” Long.MAX_VALUE, which, seems reasonable
        enough.</p>
      <p style="margin: 0px 0px 1.2em !important;">While it’s
        theoretically possible to add a different kind of segment that
        behaves in a different way (e.g. allowing negative offsets), I
        believe the cost vs. benefit ratio for doing so would be very
        unfavourable.</p>
      <blockquote style="margin: 1.2em 0px;border-left: 4px solid
        rgb(221, 221, 221); padding: 0px 1em; color: rgb(119, 119, 119);
        quotes: none;">
        <p style="margin: 0px 0px 1.2em !important;">2) The
          MemorySegment copy operation is safe for use against<br>
          overlapping ranges, and is thus a “memmove” operation. My
          application<br>
          would benefit from also having a “memcpy” operation, for those
          cases<br>
          where I know that the ranges don’t overlap. Can such an
          operation be<br>
          added?<br>
          This is not an issue, or at least not one that should be
          solved via new API surface: MemorySegment::copy relies on
          Unsafe::copyMemory which does memmove vs. memcpy depending on
          wether it can prove that ranges overlap. Rather than
          duplicating the API, if we find cases where the existing logic
          doesn’t work well, we should probably invest in rectifying
          and/or improving that logic.</p>
        <p style="margin: 0px 0px 1.2em !important;">3) Dynamic memory
          allocation is performed against Arenas, but freeing<br>
          the memory is only allowed when the Arena is closed. I find
          this to<br>
          be cumbersome at times, and in one case I ended up creating a
          single<br>
          Arena instance paired with each allocation. The other solution
          is to<br>
          directly call malloc/free, which is what I’m using in some
          places.<br>
          Both solutions are messy, so is it possible to add a simple<br>
          malloc/free API?</p>
      </blockquote>
      <p style="margin: 0px 0px 1.2em !important;">The API embraces the
        idea that one lifetime might be associated with multiple
        allocations quite deeply (this is explained in more details here
        [1]). While this is an arbitrary choice (after all, there is no
        perfect way to deal with deallocation of native resources in a
        way that is both safe and efficient), malloc/free is not the
        right primitive to design a safe API to manage off-heap
        resources for at least two reasons:</p>
      <ul style="margin: 1.2em 0px;padding-left: 2em;">
        <li style="margin: 0.5em 0px;">it is too fine-grained, there’s
          no way to group together logically-related resources (think of
          the relationship between dlopen, dlsym and dlclose)</li>
        <li style="margin: 0.5em 0px;">it is not safe-by-default: anyone
          can free a pointer, even one they did not create</li>
      </ul>
      <p style="margin: 0px 0px 1.2em !important;">In contrast, the
        lifetime-centric approach adopted by the FFM API allows
        developers to group logically related segments in the same
        lifetime, which is, often, a very useful move, and allows the
        API to scale for managing lifetime of things that are not just
        malloc’ed segments (such specifying lifetime of an upcall stub,
        or that of a native library loaded with dlopen). This allows the
        API to detect pesky conditions such as memory leaks and/or
        use-after free. There are of course cases where this way of
        doing things is not a perfect fit, and a lower-level access to
        malloc/free is preferrable. In these cases, developers can, as
        you observed, just call malloc/free downcall method handles, and
        deal with memory allocation/deallocation completely manually. Or
        they can create a one-off arena to deal with that allocation.</p>
      <p style="margin: 0px 0px 1.2em !important;">To do the latter, you
        probably would need some kind of abstraction on top:</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;">record HeapAllocation(MemorySegment segment, Arena arena) implements AutoCloseable {   
    public close() { arena().close(); }

    static HeapAllocation mallocConfined(long bytes) {
          Arena arena = Arena.ofConfined();
          return new HeapAllocation(arena.allocate(bytes), arena);
    }
}
</code></pre>
      <p style="margin: 0px 0px 1.2em !important;">To do the former you
        need to write some wrappers for malloc/free:</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;">static final MethodHandle MALLOC = Linker.nativeLinker()....
static final MethodHandle FREE = Linker.nativeLinker()....

static MemorySegment malloc(long bytes) {
    return MALLOC.invokeExact(bytes);
}

static MemorySegment free(MemorySegment segment) {
    return FREE.invokeExact(segment);
}
</code></pre>
      <p style="margin: 0px 0px 1.2em !important;">Of course the former
        approach provides more temporal safety (but might also result in
        more overhead for enforcing said safety, which, I’m not sure
        you’d be too happy with). In the latter, what you see is what
        you get, you are playing the “power user” card, ensuring
        correctness (read: avoid use-after-free) is now up to you.</p>
      <p style="margin: 0px 0px 1.2em !important;">I don’t think either
        approach looks too “messy”. Of course one-lifetime-per-segment
        is not the ideal sweet spot the FFM API is designed for, and one
        has to write some extra code, but the FFM API still allows you
        to do what you need to do (or to completely bypass temporal
        safety alltogether, if you decide to do so). After having spent
        considerable time looking at possible approaches to deal with
        memory safety, we did not find a “simpler malloc/free API” that
        was good enough as a building block for managing temporal
        resources in the FFM API.</p>
      <blockquote style="margin: 1.2em 0px;border-left: 4px solid
        rgb(221, 221, 221); padding: 0px 1em; color: rgb(119, 119, 119);
        quotes: none;">
        <p style="margin: 0px 0px 1.2em !important;">4)
          GuardUnsafeAccess. I understand that this was added to ensure
          that<br>
          accessing a memory mapped file which was been truncated
          doesn’t crash<br>
          the JVM. What is the overhead of this check? Given that my
          module<br>
          requires restricted access anyhow, it can already crash the
          JVM.<br>
          Would it be possible to support unguarded memory access
          operations<br>
          too?</p>
      </blockquote>
      <p style="margin: 0px 0px 1.2em !important;">This seems another
        case (like memcpy vs memmove) where it is assumed there’s some
        overhead associated to operation XYZ (which the JVM does to
        ensure some kind of safety in the common case), hence the
        request for a backdoor. I’d like to turn these kind of arguments
        around and instead ask for some benchmark showing that the costs
        associated with these operations are too high (and, if so, we
        might be able to find ways to improve the status quo w/o
        necessarily changing the API).</p>
      <p style="margin: 0px 0px 1.2em !important;">Cheers<br>
        Maurizio</p>
      <p style="margin: 0px 0px 1.2em !important;">[1] - <a href="https://cr.openjdk.org/~mcimadamore/panama/why_lifetimes.html" class="moz-txt-link-freetext">https://cr.openjdk.org/~mcimadamore/panama/why_lifetimes.html</a></p>
      <div title="MDH:PGJyPk9uIDEwLzA3LzIwMjMgMTY6MDIsIEJyaWFuIFMgTydOZWlsbCB3cm90ZTo8YnI+PHNwYW4gc3R5bGU9IndoaXRlLXNwYWNlOiBwcmUtd3JhcDsgZGlzcGxheTogYmxvY2s7IHdpZHRoOiA5OHZ3
OyI+Jmd0OyBJIHdhbnQgdG8gYXZvaWQgcG9sbHV0aW5nIHRoZSBvdGhlciB0aHJlYWQsIHdoaWNo
IG5vIGxvbmdlciBoYXMgYTxicj4mZ3Q7IHZhbGlkIHN1YmplY3QgbGluZSBhbnlob3cuLi48YnI+
Jmd0OyA8YnI+Jmd0OyAxKSBUaGUgc2l6ZSBsaW1pdCBvZiBhIG1lbW9yeSBzZWdtZW50IGlzIGRl
ZmluZWQgYnkgYSBzaWduZWQgdmFsdWUsPGJyPiZndDsgdGh1cyBsaW1pdGluZyB0aGUgYWRkcmVz
cyBzcGFjZSB0byBiZSA2My1iaXQuIElzIGl0IGxpa2VseSB0aGF0IGFsbDxicj4mZ3Q7IDY0LWJp
dCBhcmNoaXRlY3R1cmVzIHRvZGF5IGFuZCBpbiB0aGUgZnV0dXJlIG9ubHkgdXNlIHRoZSBsb3dl
ciBoYWxmPGJyPiZndDsgb2YgdGhlIGFkZHJlc3MgcmFuZ2U/PGJyPjwvc3Bhbj48YnI+V2hpbGUg
aXQncyB0cnVlIHRoYXQgYSBtZW1vcnkgc2VnbWVudCBjYW4gbmV2ZXIgYmUgYmlnIGVub3VnaCBh
cyB0aGUgZnVsbCBhZGRyZXNzIHNwYWNlLCBpbiByZWFsaXR5IHRoYXQgbGltaXQgaXMgYmlnIGVu
b3VnaCAtIGUuZy4gaXQgaXMgaGFyZCB0byBpbWFnaW5lIGEgZGV2ZWxvcGVyIHdhbnRpbmcgdG8g
ZXhwcmVzcyBhIHJlZ2lvbiBvZiBtZW1vcnkgd2hvc2Ugc2l6ZSBpcyBiaWdnZXIgdGhhbiAyXjYz
LiBJIGJlbGlldmUgdGhlIGFuZ2xlIHlvdSBhcmUgY29taW5nIGZyb20gaGVyZSBpcyB0aGF0IHlv
dSB3YW50IHRvIHVzZSBhIG1lbW9yeSBzZWdtZW50IHRvIG1vZGVsIHRoZSBlbnRpcmUgaGVhcCAo
YXQgbGVhc3QganVkZ2luZyBmcm9tIHRoZSBvdGhlciB0aHJlYWQgeW91IHN0YXJ0ZWQpLCBhbmQg
dGhlbiB3YW50aW5nIHRvIGp1c3QgdXNlIGEgcmF3IGxvbmcgcG9pbnRlciBhcyBhbiAib2Zmc2V0
IiBpbnRvIHRoZSBzZWdtZW50LiBHaXZlbiB0aGUgdW5zaWduZWQgbGltaXRhdGlvbnMsIHRoaXMg
d2lsbCBub3Qgd29yayAxMDAlOiB0aGUgRkZNIEFQSSBzcGVjaWZpZXMgdGhhdCB0aGUgImxvbmci
IGFyZ3VtZW50IHlvdSBwYXNzIHRvIE1lbW9yeVNlZ21lbnQ6OmdldCAoc2FtZSBmb3IgdmFyIGhh
bmRsZSkgaXMgYSBwb3NpdGl2ZSBvZmZzZXQsIHJlbGF0aXZlIHRvIHRoZSBzdGFydCBvZiB0aGUg
c2VnbWVudC4gVGhhdCBpcywgYSBuZWdhdGl2ZSBvZmZzZXQgaXMsIGJ5IGRlZmluaXRpb24swqAg
X291dHNpZGVfIHRoZSBtZW1vcnkgc2VnbWVudC4gU28sIEkgZG8gbm90IHNlZSBhIHdheSB0byBh
ZGQgc3VwcG9ydCBmb3IgZnVsbCB1bnNpZ25lZCBsb25nIGFzIG1lbW9yeSBzZWdtZW50IHNpemVz
L29mZnNldHMgLSBpbiBmYWN0LCBJIGJlbGlldmUgdGhhdCBhbGxvd2luZyBuZWdhdGl2ZSB2YWx1
ZXMgaW4gcGxhY2VzIHdoZXJlIHdlIGV4cGVjdCBhbiBvZmZzZXQgaXMgYWxtb3N0IGFsd2F5cyBh
IHNtZWxsLCBhbmQgYSBwbGFjZSBmb3IgYnVncyB0byBoaWRlLjxicj48YnI+SW4gdGVybXMgb2Yg
aW50ZXJmYWNpbmcgd2l0aCBuYXRpdmUgY29kZSwgbm90ZSB0aGF0IHRoZSBGRk0gQVBJIGNhbiBz
dGlsbCB3cmFwIHdoYXRldmVyIGFkZHJlc3MgYSBuYXRpdmUgbGlicmFyeSB0aHJvd3MgYXQgaXQs
IGJ5IHdyYXBwaW5nIHRoZSBiYXNlIGFkZHJlc3MgKGEgbG9uZykgaW50byBhIHNlZ21lbnQgdXNp
bmcgTWVtb3J5U2VnbWVudDo6b2ZBZGRyZXNzLiBUaGlzIG1ldGhvZCB0YWtlcyBhIHJhdyBhZGRy
ZXNzIHZhbHVlLCB3aGljaCBjYW4gYmUgbmVnYXRpdmUuIE9mIGNvdXJzZSB0aGUgc2l6ZSBvZiB0
aGUgc2VnbWVudCB3aWxsIGJlIGxpbWl0ZWQgdG8gIm9ubHkiIExvbmcuTUFYX1ZBTFVFLCB3aGlj
aCwgc2VlbXMgcmVhc29uYWJsZSBlbm91Z2guPGJyPjxicj5XaGlsZSBpdCdzIHRoZW9yZXRpY2Fs
bHkgcG9zc2libGUgdG8gYWRkIGEgZGlmZmVyZW50IGtpbmQgb2Ygc2VnbWVudCB0aGF0IGJlaGF2
ZXMgaW4gYSBkaWZmZXJlbnQgd2F5IChlLmcuIGFsbG93aW5nIG5lZ2F0aXZlIG9mZnNldHMpLCBJ
IGJlbGlldmUgdGhlIGNvc3QgdnMuIGJlbmVmaXQgcmF0aW8gZm9yIGRvaW5nIHNvIHdvdWxkIGJl
IHZlcnkgdW5mYXZvdXJhYmxlLjxicj48YnI+PGJyPjxzcGFuIHN0eWxlPSJ3aGl0ZS1zcGFjZTog
cHJlLXdyYXA7IGRpc3BsYXk6IGJsb2NrOyB3aWR0aDogOTh2dzsiPiZndDsgPGJyPiZndDsgMikg
VGhlIE1lbW9yeVNlZ21lbnQgY29weSBvcGVyYXRpb24gaXMgc2FmZSBmb3IgdXNlIGFnYWluc3Q8
YnI+Jmd0OyBvdmVybGFwcGluZyByYW5nZXMsIGFuZCBpcyB0aHVzIGEgIm1lbW1vdmUiIG9wZXJh
dGlvbi4gTXkgYXBwbGljYXRpb248YnI+Jmd0OyB3b3VsZCBiZW5lZml0IGZyb20gYWxzbyBoYXZp
bmcgYSAibWVtY3B5IiBvcGVyYXRpb24sIGZvciB0aG9zZSBjYXNlczxicj4mZ3Q7IHdoZXJlIEkg
a25vdyB0aGF0IHRoZSByYW5nZXMgZG9uJ3Qgb3ZlcmxhcC4gQ2FuIHN1Y2ggYW4gb3BlcmF0aW9u
IGJlPGJyPiZndDsgYWRkZWQ/PGJyPjwvc3Bhbj5UaGlzIGlzIG5vdCBhbiBpc3N1ZSwgb3IgYXQg
bGVhc3Qgbm90IG9uZSB0aGF0IHNob3VsZCBiZSBzb2x2ZWQgdmlhIG5ldyBBUEkgc3VyZmFjZTog
TWVtb3J5U2VnbWVudDo6Y29weSByZWxpZXMgb24gVW5zYWZlOjpjb3B5TWVtb3J5IHdoaWNoIGRv
ZXMgbWVtbW92ZSB2cy4gbWVtY3B5IGRlcGVuZGluZyBvbiB3ZXRoZXIgaXQgY2FuIHByb3ZlIHRo
YXQgcmFuZ2VzIG92ZXJsYXAuIFJhdGhlciB0aGFuIGR1cGxpY2F0aW5nIHRoZSBBUEksIGlmIHdl
IGZpbmQgY2FzZXMgd2hlcmUgdGhlIGV4aXN0aW5nIGxvZ2ljIGRvZXNuJ3Qgd29yayB3ZWxsLCB3
ZSBzaG91bGQgcHJvYmFibHkgaW52ZXN0IGluIHJlY3RpZnlpbmcgYW5kL29yIGltcHJvdmluZyB0
aGF0IGxvZ2ljLjxicj48c3BhbiBzdHlsZT0id2hpdGUtc3BhY2U6IHByZS13cmFwOyBkaXNwbGF5
OiBibG9jazsgd2lkdGg6IDk4dnc7Ij4mZ3Q7IDxicj4mZ3Q7IDMpIER5bmFtaWMgbWVtb3J5IGFs
bG9jYXRpb24gaXMgcGVyZm9ybWVkIGFnYWluc3QgQXJlbmFzLCBidXQgZnJlZWluZzxicj4mZ3Q7
IHRoZSBtZW1vcnkgaXMgb25seSBhbGxvd2VkIHdoZW4gdGhlIEFyZW5hIGlzIGNsb3NlZC4gSSBm
aW5kIHRoaXMgdG88YnI+Jmd0OyBiZSBjdW1iZXJzb21lIGF0IHRpbWVzLCBhbmQgaW4gb25lIGNh
c2UgSSBlbmRlZCB1cCBjcmVhdGluZyBhIHNpbmdsZTxicj4mZ3Q7IEFyZW5hIGluc3RhbmNlIHBh
aXJlZCB3aXRoIGVhY2ggYWxsb2NhdGlvbi4gVGhlIG90aGVyIHNvbHV0aW9uIGlzIHRvPGJyPiZn
dDsgZGlyZWN0bHkgY2FsbCBtYWxsb2MvZnJlZSwgd2hpY2ggaXMgd2hhdCBJJ20gdXNpbmcgaW4g
c29tZSBwbGFjZXMuPGJyPiZndDsgQm90aCBzb2x1dGlvbnMgYXJlIG1lc3N5LCBzbyBpcyBpdCBw
b3NzaWJsZSB0byBhZGQgYSBzaW1wbGU8YnI+Jmd0OyBtYWxsb2MvZnJlZSBBUEk/PGJyPjwvc3Bh
bj48YnI+VGhlIEFQSSBlbWJyYWNlcyB0aGUgaWRlYSB0aGF0IG9uZSBsaWZldGltZSBtaWdodCBi
ZSBhc3NvY2lhdGVkIHdpdGggbXVsdGlwbGUgYWxsb2NhdGlvbiBxdWl0ZSBkZWVwbHkgKHRoaXMg
aXMgZXhwbGFpbmVkIGluIG1vcmUgZGV0YWlscyBoZXJlIFsxXSkuIFdoaWxlIHRoaXMgaXMgYW4g
YXJiaXRyYXJ5IGNob2ljZSAoYWZ0ZXIgYWxsLCB0aGVyZSBpcyBubyBwZXJmZWN0IHdheSB0byBk
ZWFsIHdpdGggZGVhbGxvY2F0aW9uIG9mIG5hdGl2ZSByZXNvdXJjZXMgaW4gYSB3YXkgdGhhdCBp
cyBib3RoIHNhZmUgYW5kIGVmZmljaWVudCksIG1hbGxvYy9mcmVlIGlzIG5vdCB0aGUgcmlnaHQg
cHJpbWl0aXZlIHRvIGRlc2lnbiBhIHNhZmUgQVBJIHRvIG1hbmFnZSBvZmYtaGVhcCByZXNvdXJj
ZXMgZm9yIGF0IGxlYXN0IHR3byByZWFzb25zOjxicj48YnI+KiBpdCBpcyB0b28gZmluZS1ncmFp
bmVkLCB0aGVyZSdzIG5vIHdheSB0byBncm91cCB0b2dldGhlciBsb2dpY2FsbHktcmVsYXRlZCBy
ZXNvdXJjZXMgKHRoaW5rIG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBkbG9wZW4sIGRsc3lt
IGFuZCBkbGNsb3NlKTxicj4qIGl0IGlzIG5vdCBzYWZlLWJ5LWRlZmF1bHQ6IGFueW9uZSBjYW4g
ZnJlZSBhIHBvaW50ZXIsIGV2ZW4gb25lIHRoZXkgZGlkIG5vdCBjcmVhdGU8YnI+PGJyPkluIGNv
bnRyYXN0LCB0aGUgbGlmZXRpbWUtY2VudHJpYyBhcHByb2FjaCBhZG9wdGVkIGJ5IHRoZSBGRk0g
QVBJIGFsbG93cyBkZXZlbG9wZXJzIHRvIGdyb3VwIGxvZ2ljYWxseSByZWxhdGVkIHNlZ21lbnRz
IGluIHRoZSBzYW1lIGxpZmV0aW1lLCB3aGljaCBpcywgb2Z0ZW4sIGEgdmVyeSB1c2VmdWwgbW92
ZSwgYW5kIGFsbG93cyB0aGUgQVBJIHRvIHNjYWxlIGZvciBtYW5hZ2luZyBsaWZldGltZSBvZiB0
aGluZ3MgdGhhdCBhcmUgbm90IGp1c3QgbWFsbG9jJ2VkIHNlZ21lbnRzIChzdWNoIHNwZWNpZnlp
bmcgbGlmZXRpbWUgb2YgYW4gdXBjYWxsIHN0dWIsIG9yIHRoYXQgb2YgYSBuYXRpdmUgbGlicmFy
eSBsb2FkZWQgd2l0aCBkbG9wZW4pLiBUaGlzIGFsbG93cyB0aGUgQVBJIHRvIGRldGVjdCBwZXNr
eSBjb25kaXRpb25zIHN1Y2ggYXMgbWVtb3J5IGxlYWtzIGFuZC9vciB1c2UtYWZ0ZXIgZnJlZS4g
VGhlcmUgYXJlIG9mIGNvdXJzZSBjYXNlcyB3aGVyZSB0aGlzIHdheSBvZiBkb2luZyB0aGluZ3Mg
aXMgbm90IHBlcmZlY3QsIGFuZCBhIGxvd2VyLWxldmVsIGFjY2VzcyB0byBtYWxsb2MvZnJlZSBp
cyBwcmVmZXJyYWJsZS4gSW4gdGhlc2UgY2FzZXMsIGRldmVsb3BlcnMgY2FuLCBhcyB5b3Ugb2Jz
ZXJ2ZWQsIGp1c3QgY2FsbCBtYWxsb2MvZnJlZSBkb3duY2FsbCBtZXRob2QgaGFuZGxlcywgYW5k
IGRlYWwgd2l0aCBtZW1vcnkgYWxsb2NhdGlvbi9kZWFsbG9jYXRpb24gY29tcGxldGVseSBtYW51
YWxseS4gT3IgdGhleSBjYW4gY3JlYXRlIGEgb25lLW9mZiBhcmVuYSB0byBkZWFsIHdpdGggdGhh
dCBhbGxvY2F0aW9uLjxicj48YnI+VG8gZG8gdGhlIGZvcm1lciwgeW91IHByb2JhYmx5IHdvdWxk
IG5lZWQgc29tZSBraW5kIG9mIGFic3RyYWN0aW9uIG9uIHRvcDo8YnI+PGJyPmBgYDxicj5yZWNv
cmQgSGVhcEFsbG9jYXRpb24oTWVtb3J5U2VnbWVudCBzZWdtZW50LCBBcmVuYSBhcmVuYSkgaW1w
bGVtZW50cyBBdXRvQ2xvc2VhYmxlIHvCoCDCoDxicj7CoMKgwqAgcHVibGljIGNsb3NlKCkgeyBh
cmVuYSgpLmNsb3NlKCk7IH08YnI+PGJyPsKgwqDCoCBzdGF0aWMgSGVhcEFsbG9jYXRpb24gbWFs
bG9jQ29uZmluZWQobG9uZyBieXRlcykgezxicj7CoMKgwqDCoMKgwqDCoMKgwqAgQXJlbmEgYXJl
bmEgPSBBcmVuYS5vZkNvbmZpbmVkKCk7PGJyPsKgwqDCoMKgwqDCoMKgwqDCoCByZXR1cm4gbmV3
IEhlYXBBbGxvY2F0aW9uKGFyZW5hLmFsbG9jYXRlKGJ5dGVzKSwgYXJlbmEpOzxicj7CoMKgwqAg
fTxicj59PGJyPmBgYDxicj48YnI+VG8gZG8gdGhlIGxhdHRlciB5b3UgbmVlZCB0byB3cml0ZSBz
b21lIHdyYXBwZXJzIGZvciBtYWxsb2MvZnJlZTo8YnI+PGJyPmBgYDxicj5zdGF0aWMgZmluYWwg
TWV0aG9kSGFuZGxlIE1BTExPQyA9IExpbmtlci5uYXRpdmVMaW5rZXIoKS4uLi48YnI+c3RhdGlj
IGZpbmFsIE1ldGhvZEhhbmRsZSBGUkVFID0gTGlua2VyLm5hdGl2ZUxpbmtlcigpLi4uLjxicj48
YnI+c3RhdGljIE1lbW9yeVNlZ21lbnQgbWFsbG9jKGxvbmcgYnl0ZXMpIHs8YnI+wqDCoMKgIHJl
dHVybiBNQUxMT0MuaW52b2tlRXhhY3QoYnl0ZXMpOzxicj59PGJyPjxicj5zdGF0aWMgTWVtb3J5
U2VnbWVudCBmcmVlKE1lbW9yeVNlZ21lbnQgc2VnbWVudCkgezxicj7CoMKgwqAgcmV0dXJuIEZS
RUUuaW52b2tlRXhhY3Qoc2VnbWVudCk7PGJyPn08YnI+YGBgPGJyPjxicj5PZiBjb3Vyc2UgdGhl
IGZvcm1lciBhcHByb2FjaCBwcm92aWRlcyBtb3JlIHRlbXBvcmFsIHNhZmV0eSAoYnV0IG1pZ2h0
IGFsc28gcmVzdWx0IGluIG1vcmUgb3ZlcmhlYWQgZm9yIGVuZm9yY2luZyBzYWlkIHNhZmV0eSwg
d2hpY2gsIEknbSBub3Qgc3VyZSB5b3UnZCBiZSB0b28gaGFwcHkgd2l0aCkuIEluIHRoZSBsYXR0
ZXIsIHdoYXQgeW91IHNlZSBpcyB3aGF0IHlvdSBnZXQsIHlvdSBhcmUgcGxheWluZyB0aGUgInBv
d2VyIHVzZXIiIGNhcmQsIGVuc3VyaW5nIGNvcnJlY3RuZXNzIChyZWFkOiBhdm9pZCB1c2UtYWZ0
ZXItZnJlZSkgaXMgbm93IHVwIHRvIHlvdS48YnI+PGJyPkkgZG9uJ3QgdGhpbmsgZWl0aGVyIGFw
cHJvYWNoIGxvb2tzIHRvbyAibWVzc3kiLsKgIE9mIGNvdXJzZSBvbmUtbGlmZXRpbWUtcGVyLXNl
Z21lbnQgaXMgbm90IHRoZSBpZGVhbCBzd2VldCBzcG90IHRoZSBGRk0gQVBJIGlzIGRlc2lnbmVk
IGZvciwgYW5kIG9uZSBoYXMgdG8gd3JpdGUgc29tZSBleHRyYSBjb2RlLCBidXQgdGhlIEZGTSBB
UEkgc3RpbGwgYWxsb3dzIHlvdSB0byBkbyB3aGF0IHlvdSBuZWVkIHRvIGRvIChvciB0byBjb21w
bGV0ZWx5IGJ5cGFzcyB0ZW1wb3JhbCBzYWZldHkgYWxsdG9nZXRoZXIsIGlmIHlvdSBkZWNpZGUg
dG8gZG8gc28pLiBBZnRlciBoYXZpbmcgc3BlbnQgY29uc2lkZXJhYmxlIHRpbWUgbG9va2luZyBh
dCBwb3NzaWJsZSBhcHByb2FjaGVzIHRvIGRlYWwgd2l0aCBtZW1vcnkgc2FmZXR5LCB3ZSBkaWQg
bm90IGZpbmQgYSAic2ltcGxlciBtYWxsb2MvZnJlZSBBUEkiIHRoYXQgd2FzIGdvb2QgZW5vdWdo
IGFzIGEgYnVpbGRpbmcgYmxvY2sgZm9yIG1hbmFnaW5nIHRlbXBvcmFsIHJlc291cmNlcyBpbiB0
aGUgRkZNIEFQSS48YnI+PGJyPjxicj48c3BhbiBzdHlsZT0id2hpdGUtc3BhY2U6IHByZS13cmFw
OyBkaXNwbGF5OiBibG9jazsgd2lkdGg6IDk4dnc7Ij4mZ3Q7IDxicj4mZ3Q7IDQpIEd1YXJkVW5z
YWZlQWNjZXNzLiBJIHVuZGVyc3RhbmQgdGhhdCB0aGlzIHdhcyBhZGRlZCB0byBlbnN1cmUgdGhh
dDxicj4mZ3Q7IGFjY2Vzc2luZyBhIG1lbW9yeSBtYXBwZWQgZmlsZSB3aGljaCB3YXMgYmVlbiB0
cnVuY2F0ZWQgZG9lc24ndCBjcmFzaDxicj4mZ3Q7IHRoZSBKVk0uIFdoYXQgaXMgdGhlIG92ZXJo
ZWFkIG9mIHRoaXMgY2hlY2s/IEdpdmVuIHRoYXQgbXkgbW9kdWxlPGJyPiZndDsgcmVxdWlyZXMg
cmVzdHJpY3RlZCBhY2Nlc3MgYW55aG93LCBpdCBjYW4gYWxyZWFkeSBjcmFzaCB0aGUgSlZNLjxi
cj4mZ3Q7IFdvdWxkIGl0IGJlIHBvc3NpYmxlIHRvIHN1cHBvcnQgdW5ndWFyZGVkIG1lbW9yeSBh
Y2Nlc3Mgb3BlcmF0aW9uczxicj4mZ3Q7IHRvbz88YnI+PC9zcGFuPjxicj5UaGlzIHNlZW1zIGFu
b3RoZXIgY2FzZSAobGlrZSBtZW1jcHkgdnMgbWVtbW92ZSkgd2hlcmUgaXQgaXMgYXNzdW1lZCB0
aGVyZSdzIHNvbWUgb3ZlcmhlYWQgYXNzb2NpYXRlZCB0byBvcGVyYXRpb24gWFlaICh3aGljaCB0
aGUgSlZNIGRvZXMgdG8gZW5zdXJlIHNvbWUga2luZCBvZiBzYWZldHkgaW4gdGhlIGNvbW1vbiBj
YXNlKSwgaGVuY2UgdGhlIHJlcXVlc3QgZm9yIGEgYmFja2Rvb3IuIEknZCBsaWtlIHRvIHR1cm4g
dGhlc2Uga2luZCBvZiBhcmd1bWVudHMgYXJvdW5kIGFuZCBpbnN0ZWFkIGFzayBmb3Igc29tZSBi
ZW5jaG1hcmsgdGhhdCBzaG93IHRoYXQgdGhlIGNvc3QgYXNzb2NpYXRlZCB3aXRoIHRoZXNlIGV4
dHJhIG9wZXJhdGlvbiBpcyB0b28gaGlnaCAoYW5kLCBpZiBzbywgd2UgbWlnaHQgYmUgYWJsZSB0
byBmaW5kIHdheXMgdG8gaW1wcm92ZSB0aGUgc3RhdHVzIHF1byB3L28gbmVjZXNzYXJpbHkgY2hh
bmdpbmcgdGhlIEFQSSkuPGJyPjxicj5DaGVlcnM8YnI+TWF1cml6aW88YnI+PGJyPlsxXSAtIGh0
dHBzOi8vY3Iub3Blbmpkay5vcmcvfm1jaW1hZGFtb3JlL3BhbmFtYS93aHlfbGlmZXRpbWVzLmh0
        bWw8YnI+PGJyPjxicj4=" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0;">​</div>
    </div>
  </body>
</html>