Re: RFR: 8254162: Implementation of Foreign-Memory Access API (Third Incubator) [v3]

2020-10-09 Thread Maurizio Cimadamore
On Thu, 8 Oct 2020 23:17:33 GMT, Paul Sandoz  wrote:

>> Maurizio Cimadamore has updated the pull request incrementally with one 
>> additional commit since the last revision:
>> 
>>   Fix indent in GensrcScopedMemoryAccess.gmk
>
> Reviewed this when updated in 
> [panama-foreign](https://github.com/openjdk/panama-foreign/tree/foreign-memaccess),
>  hence
> the lack of substantial comments for this PR.

When re-running all benchmarks, I noted an issue with the `BulkOps` 
microbenchmark: calling `MemorySegment::mismatch`
on a small segment (< 8 bytes) was 10x slower than with ByteBuffers. After some 
investigation, I realized that the
issue is caused by the fact that the `AbstractMemorySegmentImpl::mismatch` 
method contains inexact var handle calls,
where the segment coordinate has type `AbstractMemorySegmentImpl` instead of 
the expected `MemorySegment`, so we take
the slow path.

A simple solution is to avoid using var handles directly here, and use the 
helper functions in MemoryAccess, which
widens the type accordingly and produce an exact var handle call.

With this change, perfomance of mismatch on small segment is on par with 
ByteBuffer.

-

PR: https://git.openjdk.java.net/jdk/pull/548


Re: RFR: 8254162: Implementation of Foreign-Memory Access API (Third Incubator) [v3]

2020-10-08 Thread Paul Sandoz
On Thu, 8 Oct 2020 13:59:20 GMT, Maurizio Cimadamore  
wrote:

>> This patch contains the changes associated with the third incubation round 
>> of the foreign memory access API incubation
>> (see JEP 393 [1]). This iteration focus on improving the usability of the 
>> API in 3 main ways:
>> * first, by providing a way to obtain truly *shared* segments, which can be 
>> accessed and closed concurrently from
>>   multiple threads
>> * second, by providing a way to register a memory segment against a 
>> `Cleaner`, so as to have some (optional) guarantee
>>   that the memory will be deallocated, eventually
>> * third, by not requiring users to dive deep into var handles when they 
>> first pick up the API; a new `MemoryAccess` class
>>   has been added, which defines several useful dereference routines; these 
>> are really just thin wrappers around memory
>>   access var handles, but they make the barrier of entry for using this API 
>> somewhat lower.
>> 
>> A big conceptual shift that comes with this API refresh is that the role of 
>> `MemorySegment` and `MemoryAddress` is not
>> the same as it used to be; it used to be the case that a memory address 
>> could (sometimes, not always) have a back link
>> to the memory segment which originated it; additionally, memory access var 
>> handles used `MemoryAddress` as a basic unit
>> of dereference.  This has all changed as per this API refresh;  now a 
>> `MemoryAddress` is just a dumb carrier which
>> wraps a pair of object/long addressing coordinates; `MemorySegment` has 
>> become the star of the show, as far as
>> dereferencing memory is concerned. You cannot dereference memory if you 
>> don't have a segment. This improves usability
>> in a number of ways - first, it is a lot easier to wrap native addresses 
>> (`long`, essentially) into a `MemoryAddress`;
>> secondly, it is crystal clear what a client has to do in order to 
>> dereference memory: if a client has a segment, it can
>> use that; otherwise, if the client only has an address, it will have to 
>> create a segment *unsafely* (this can be done
>> by calling `MemoryAddress::asSegmentRestricted`).  A list of the API, 
>> implementation and test changes is provided
>> below. If  you have any questions, or need more detailed explanations, I 
>> (and the  rest of the Panama team) will be
>> happy to point at existing discussions,  and/or to provide the feedback 
>> required.   A big thank to Erik Osterlund,
>> Vladimir Ivanov and David Holmes, without whom the work on shared memory 
>> segment would not have been possible; also I'd
>> like to thank Paul Sandoz, whose insights on API design have been very 
>> helpful in this journey.  Thanks  Maurizio
>> Javadoc:   
>> http://cr.openjdk.java.net/~mcimadamore/8254162_v1/javadoc/jdk/incubator/foreign/package-summary.html
>> Specdiff:
>> 
>> http://cr.openjdk.java.net/~mcimadamore/8254162_v1/specdiff/jdk/incubator/foreign/package-summary.html
>> 
>> CSR:
>> 
>> https://bugs.openjdk.java.net/browse/JDK-8254163
>> 
>> 
>> 
>> ### API Changes
>> 
>> * `MemorySegment`
>>   * drop factory for restricted segment (this has been moved to 
>> `MemoryAddress`, see below)
>>   * added a no-arg factory for a native restricted segment representing 
>> entire native heap
>>   * rename `withOwnerThread` to `handoff`
>>   * add new `share` method, to create shared segments
>>   * add new `registerCleaner` method, to register a segment against a cleaner
>>   * add more helpers to create arrays from a segment e.g. `toIntArray`
>>   * add some `asSlice` overloads (to make up for the fact that now segments 
>> are more frequently used as cursors)
>>   * rename `baseAddress` to `address` (so that `MemorySegment` can implement 
>> `Addressable`)
>> * `MemoryAddress`
>>   * drop `segment` accessor
>>   * drop `rebase` method and replace it with `segmentOffset` which returns 
>> the offset (a `long`) of this address relative
>> to a given segment
>> * `MemoryAccess`
>>   * New class supporting several static dereference helpers; the helpers are 
>> organized by carrier and access mode, where a
>> carrier is one of the usual suspect (a Java primitive, minus `boolean`); 
>> the access mode can be simple (e.g. access
>> base address of given segment), or indexed, in which case the accessor 
>> takes a segment and either a low-level byte
>> offset,or a high level logical index. The classification is reflected in 
>> the naming scheme (e.g. `getByte` vs.
>> `getByteAtOffset` vs `getByteAtIndex`).
>> * `MemoryHandles`
>>   * drop `withOffset` combinator
>>   * drop `withStride` combinator
>>   * the basic memory access handle factory now returns a var handle which 
>> takes a `MemorySegment` and a `long` - from which
>> it is easy to derive all the other handles using plain var handle 
>> combinators.
>> * `Addressable`
>>   * This is a new interface which is attached to entities which can be 
>> projected to a `MemoryAddress`. For now, both
>> `MemoryAdd

Re: RFR: 8254162: Implementation of Foreign-Memory Access API (Third Incubator) [v3]

2020-10-08 Thread Coleen Phillimore
On Thu, 8 Oct 2020 13:59:20 GMT, Maurizio Cimadamore  
wrote:

>> This patch contains the changes associated with the third incubation round 
>> of the foreign memory access API incubation
>> (see JEP 393 [1]). This iteration focus on improving the usability of the 
>> API in 3 main ways:
>> * first, by providing a way to obtain truly *shared* segments, which can be 
>> accessed and closed concurrently from
>>   multiple threads
>> * second, by providing a way to register a memory segment against a 
>> `Cleaner`, so as to have some (optional) guarantee
>>   that the memory will be deallocated, eventually
>> * third, by not requiring users to dive deep into var handles when they 
>> first pick up the API; a new `MemoryAccess` class
>>   has been added, which defines several useful dereference routines; these 
>> are really just thin wrappers around memory
>>   access var handles, but they make the barrier of entry for using this API 
>> somewhat lower.
>> 
>> A big conceptual shift that comes with this API refresh is that the role of 
>> `MemorySegment` and `MemoryAddress` is not
>> the same as it used to be; it used to be the case that a memory address 
>> could (sometimes, not always) have a back link
>> to the memory segment which originated it; additionally, memory access var 
>> handles used `MemoryAddress` as a basic unit
>> of dereference.  This has all changed as per this API refresh;  now a 
>> `MemoryAddress` is just a dumb carrier which
>> wraps a pair of object/long addressing coordinates; `MemorySegment` has 
>> become the star of the show, as far as
>> dereferencing memory is concerned. You cannot dereference memory if you 
>> don't have a segment. This improves usability
>> in a number of ways - first, it is a lot easier to wrap native addresses 
>> (`long`, essentially) into a `MemoryAddress`;
>> secondly, it is crystal clear what a client has to do in order to 
>> dereference memory: if a client has a segment, it can
>> use that; otherwise, if the client only has an address, it will have to 
>> create a segment *unsafely* (this can be done
>> by calling `MemoryAddress::asSegmentRestricted`).  A list of the API, 
>> implementation and test changes is provided
>> below. If  you have any questions, or need more detailed explanations, I 
>> (and the  rest of the Panama team) will be
>> happy to point at existing discussions,  and/or to provide the feedback 
>> required.   A big thank to Erik Osterlund,
>> Vladimir Ivanov and David Holmes, without whom the work on shared memory 
>> segment would not have been possible; also I'd
>> like to thank Paul Sandoz, whose insights on API design have been very 
>> helpful in this journey.  Thanks  Maurizio
>> Javadoc:   
>> http://cr.openjdk.java.net/~mcimadamore/8254162_v1/javadoc/jdk/incubator/foreign/package-summary.html
>> Specdiff:
>> 
>> http://cr.openjdk.java.net/~mcimadamore/8254162_v1/specdiff/jdk/incubator/foreign/package-summary.html
>> 
>> CSR:
>> 
>> https://bugs.openjdk.java.net/browse/JDK-8254163
>> 
>> 
>> 
>> ### API Changes
>> 
>> * `MemorySegment`
>>   * drop factory for restricted segment (this has been moved to 
>> `MemoryAddress`, see below)
>>   * added a no-arg factory for a native restricted segment representing 
>> entire native heap
>>   * rename `withOwnerThread` to `handoff`
>>   * add new `share` method, to create shared segments
>>   * add new `registerCleaner` method, to register a segment against a cleaner
>>   * add more helpers to create arrays from a segment e.g. `toIntArray`
>>   * add some `asSlice` overloads (to make up for the fact that now segments 
>> are more frequently used as cursors)
>>   * rename `baseAddress` to `address` (so that `MemorySegment` can implement 
>> `Addressable`)
>> * `MemoryAddress`
>>   * drop `segment` accessor
>>   * drop `rebase` method and replace it with `segmentOffset` which returns 
>> the offset (a `long`) of this address relative
>> to a given segment
>> * `MemoryAccess`
>>   * New class supporting several static dereference helpers; the helpers are 
>> organized by carrier and access mode, where a
>> carrier is one of the usual suspect (a Java primitive, minus `boolean`); 
>> the access mode can be simple (e.g. access
>> base address of given segment), or indexed, in which case the accessor 
>> takes a segment and either a low-level byte
>> offset,or a high level logical index. The classification is reflected in 
>> the naming scheme (e.g. `getByte` vs.
>> `getByteAtOffset` vs `getByteAtIndex`).
>> * `MemoryHandles`
>>   * drop `withOffset` combinator
>>   * drop `withStride` combinator
>>   * the basic memory access handle factory now returns a var handle which 
>> takes a `MemorySegment` and a `long` - from which
>> it is easy to derive all the other handles using plain var handle 
>> combinators.
>> * `Addressable`
>>   * This is a new interface which is attached to entities which can be 
>> projected to a `MemoryAddress`. For now, both
>> `MemoryAdd

Re: RFR: 8254162: Implementation of Foreign-Memory Access API (Third Incubator) [v3]

2020-10-08 Thread Erik Joelsson
On Thu, 8 Oct 2020 13:59:20 GMT, Maurizio Cimadamore  
wrote:

>> This patch contains the changes associated with the third incubation round 
>> of the foreign memory access API incubation
>> (see JEP 393 [1]). This iteration focus on improving the usability of the 
>> API in 3 main ways:
>> * first, by providing a way to obtain truly *shared* segments, which can be 
>> accessed and closed concurrently from
>>   multiple threads
>> * second, by providing a way to register a memory segment against a 
>> `Cleaner`, so as to have some (optional) guarantee
>>   that the memory will be deallocated, eventually
>> * third, by not requiring users to dive deep into var handles when they 
>> first pick up the API; a new `MemoryAccess` class
>>   has been added, which defines several useful dereference routines; these 
>> are really just thin wrappers around memory
>>   access var handles, but they make the barrier of entry for using this API 
>> somewhat lower.
>> 
>> A big conceptual shift that comes with this API refresh is that the role of 
>> `MemorySegment` and `MemoryAddress` is not
>> the same as it used to be; it used to be the case that a memory address 
>> could (sometimes, not always) have a back link
>> to the memory segment which originated it; additionally, memory access var 
>> handles used `MemoryAddress` as a basic unit
>> of dereference.  This has all changed as per this API refresh;  now a 
>> `MemoryAddress` is just a dumb carrier which
>> wraps a pair of object/long addressing coordinates; `MemorySegment` has 
>> become the star of the show, as far as
>> dereferencing memory is concerned. You cannot dereference memory if you 
>> don't have a segment. This improves usability
>> in a number of ways - first, it is a lot easier to wrap native addresses 
>> (`long`, essentially) into a `MemoryAddress`;
>> secondly, it is crystal clear what a client has to do in order to 
>> dereference memory: if a client has a segment, it can
>> use that; otherwise, if the client only has an address, it will have to 
>> create a segment *unsafely* (this can be done
>> by calling `MemoryAddress::asSegmentRestricted`).  A list of the API, 
>> implementation and test changes is provided
>> below. If  you have any questions, or need more detailed explanations, I 
>> (and the  rest of the Panama team) will be
>> happy to point at existing discussions,  and/or to provide the feedback 
>> required.   A big thank to Erik Osterlund,
>> Vladimir Ivanov and David Holmes, without whom the work on shared memory 
>> segment would not have been possible; also I'd
>> like to thank Paul Sandoz, whose insights on API design have been very 
>> helpful in this journey.  Thanks  Maurizio
>> Javadoc:   
>> http://cr.openjdk.java.net/~mcimadamore/8254162_v1/javadoc/jdk/incubator/foreign/package-summary.html
>> Specdiff:
>> 
>> http://cr.openjdk.java.net/~mcimadamore/8254162_v1/specdiff/jdk/incubator/foreign/package-summary.html
>> 
>> CSR:
>> 
>> https://bugs.openjdk.java.net/browse/JDK-8254163
>> 
>> 
>> 
>> ### API Changes
>> 
>> * `MemorySegment`
>>   * drop factory for restricted segment (this has been moved to 
>> `MemoryAddress`, see below)
>>   * added a no-arg factory for a native restricted segment representing 
>> entire native heap
>>   * rename `withOwnerThread` to `handoff`
>>   * add new `share` method, to create shared segments
>>   * add new `registerCleaner` method, to register a segment against a cleaner
>>   * add more helpers to create arrays from a segment e.g. `toIntArray`
>>   * add some `asSlice` overloads (to make up for the fact that now segments 
>> are more frequently used as cursors)
>>   * rename `baseAddress` to `address` (so that `MemorySegment` can implement 
>> `Addressable`)
>> * `MemoryAddress`
>>   * drop `segment` accessor
>>   * drop `rebase` method and replace it with `segmentOffset` which returns 
>> the offset (a `long`) of this address relative
>> to a given segment
>> * `MemoryAccess`
>>   * New class supporting several static dereference helpers; the helpers are 
>> organized by carrier and access mode, where a
>> carrier is one of the usual suspect (a Java primitive, minus `boolean`); 
>> the access mode can be simple (e.g. access
>> base address of given segment), or indexed, in which case the accessor 
>> takes a segment and either a low-level byte
>> offset,or a high level logical index. The classification is reflected in 
>> the naming scheme (e.g. `getByte` vs.
>> `getByteAtOffset` vs `getByteAtIndex`).
>> * `MemoryHandles`
>>   * drop `withOffset` combinator
>>   * drop `withStride` combinator
>>   * the basic memory access handle factory now returns a var handle which 
>> takes a `MemorySegment` and a `long` - from which
>> it is easy to derive all the other handles using plain var handle 
>> combinators.
>> * `Addressable`
>>   * This is a new interface which is attached to entities which can be 
>> projected to a `MemoryAddress`. For now, both
>> `MemoryAdd

Re: RFR: 8254162: Implementation of Foreign-Memory Access API (Third Incubator) [v3]

2020-10-08 Thread Maurizio Cimadamore
> This patch contains the changes associated with the third incubation round of 
> the foreign memory access API incubation
> (see JEP 393 [1]). This iteration focus on improving the usability of the API 
> in 3 main ways:
> * first, by providing a way to obtain truly *shared* segments, which can be 
> accessed and closed concurrently from
>   multiple threads
> * second, by providing a way to register a memory segment against a 
> `Cleaner`, so as to have some (optional) guarantee
>   that the memory will be deallocated, eventually
> * third, by not requiring users to dive deep into var handles when they first 
> pick up the API; a new `MemoryAccess` class
>   has been added, which defines several useful dereference routines; these 
> are really just thin wrappers around memory
>   access var handles, but they make the barrier of entry for using this API 
> somewhat lower.
> 
> A big conceptual shift that comes with this API refresh is that the role of 
> `MemorySegment` and `MemoryAddress` is not
> the same as it used to be; it used to be the case that a memory address could 
> (sometimes, not always) have a back link
> to the memory segment which originated it; additionally, memory access var 
> handles used `MemoryAddress` as a basic unit
> of dereference.  This has all changed as per this API refresh;  now a 
> `MemoryAddress` is just a dumb carrier which
> wraps a pair of object/long addressing coordinates; `MemorySegment` has 
> become the star of the show, as far as
> dereferencing memory is concerned. You cannot dereference memory if you don't 
> have a segment. This improves usability
> in a number of ways - first, it is a lot easier to wrap native addresses 
> (`long`, essentially) into a `MemoryAddress`;
> secondly, it is crystal clear what a client has to do in order to dereference 
> memory: if a client has a segment, it can
> use that; otherwise, if the client only has an address, it will have to 
> create a segment *unsafely* (this can be done
> by calling `MemoryAddress::asSegmentRestricted`).  A list of the API, 
> implementation and test changes is provided
> below. If  you have any questions, or need more detailed explanations, I (and 
> the  rest of the Panama team) will be
> happy to point at existing discussions,  and/or to provide the feedback 
> required.   A big thank to Erik Osterlund,
> Vladimir Ivanov and David Holmes, without whom the work on shared memory 
> segment would not have been possible; also I'd
> like to thank Paul Sandoz, whose insights on API design have been very 
> helpful in this journey.  Thanks  Maurizio
> Javadoc:   
> http://cr.openjdk.java.net/~mcimadamore/8254162_v1/javadoc/jdk/incubator/foreign/package-summary.html
> Specdiff:
> 
> http://cr.openjdk.java.net/~mcimadamore/8254162_v1/specdiff/jdk/incubator/foreign/package-summary.html
> 
> CSR:
> 
> https://bugs.openjdk.java.net/browse/JDK-8254163
> 
> 
> 
> ### API Changes
> 
> * `MemorySegment`
>   * drop factory for restricted segment (this has been moved to 
> `MemoryAddress`, see below)
>   * added a no-arg factory for a native restricted segment representing 
> entire native heap
>   * rename `withOwnerThread` to `handoff`
>   * add new `share` method, to create shared segments
>   * add new `registerCleaner` method, to register a segment against a cleaner
>   * add more helpers to create arrays from a segment e.g. `toIntArray`
>   * add some `asSlice` overloads (to make up for the fact that now segments 
> are more frequently used as cursors)
>   * rename `baseAddress` to `address` (so that `MemorySegment` can implement 
> `Addressable`)
> * `MemoryAddress`
>   * drop `segment` accessor
>   * drop `rebase` method and replace it with `segmentOffset` which returns 
> the offset (a `long`) of this address relative
> to a given segment
> * `MemoryAccess`
>   * New class supporting several static dereference helpers; the helpers are 
> organized by carrier and access mode, where a
> carrier is one of the usual suspect (a Java primitive, minus `boolean`); 
> the access mode can be simple (e.g. access
> base address of given segment), or indexed, in which case the accessor 
> takes a segment and either a low-level byte
> offset,or a high level logical index. The classification is reflected in 
> the naming scheme (e.g. `getByte` vs.
> `getByteAtOffset` vs `getByteAtIndex`).
> * `MemoryHandles`
>   * drop `withOffset` combinator
>   * drop `withStride` combinator
>   * the basic memory access handle factory now returns a var handle which 
> takes a `MemorySegment` and a `long` - from which
> it is easy to derive all the other handles using plain var handle 
> combinators.
> * `Addressable`
>   * This is a new interface which is attached to entities which can be 
> projected to a `MemoryAddress`. For now, both
> `MemoryAddress` and `MemorySegment` implement it; we have plans, with JEP 
> 389 [2] to add more implementations. Clients
> can largely ignore this interface, which co