Slice a MemorySegment using SequenceLayout's element boundaries

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Jan 12 11:20:16 UTC 2022


On 12/01/2022 09:08, Sebastian Stenzel wrote:
> Hi Maurizio,
>
> thanks for the fast reply. While your suggested method may achieve the same, it doesn't really appeal to me. Creating a method handle and invoking it (i.e. without any type safety) isn't any less complicated than my original code. Or maybe I didn't understand it correct yet?

Well, you can create the method handle, store it in a static final 
constant - then wrap it with a static method if you want (static) type 
safety. The problem here is that when accessing a layout path there are 
an unknown number of coordinates involved (the API I pointed out is 
general, and allows you also to access structs nested into structs 
nested into arrays, etc.).

In your case, it seems like you have a memory segment which contains a 
bunch of structs with given layouts. If you don't want the slicing 
method handle, and you don't want to do manual offset computation, 
perhaps you could try with MemorySegment::element(MemoryLayout). This 
gives you a Stream of slices, with given layout. But not 100% is simpler 
that your original approach - especially if you only ever need two slices.

But you can do:

var slices = segment.elements(structLayout).toList();
var elem0 = slices.get(0);
var elem1 = slices.get(1);

Maurizio

>
>
>> On 11. Jan 2022, at 22:08, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>>
>> Hi Sebastian,
>> look at the MemoryLayouy::sliceHandle - I believe it should do what you want? It takes a sequence of PathElements and returns a MethodHandle which takes a MemorySegment and some long coordinates and return the segment slice at that coordinates, which seems to be what you are trying to do.
>>
>> Cheers
>> Maurizio
>>
>> On 11/01/2022 20:48, Sebastian Stenzel wrote:
>>> Hi,
>>>
>>> I've just updated some of my experiments [1] using the latest API in the upcoming JDK 18. Which lead to a question:
>>>
>>> Given:
>>>
>>> 1. a MemoryAddress (parameter in an upcall stub) representing a pointer to an array of structs
>>> 2. a matching SequenceLayout of GroupLayouts for this array of structs
>>>
>>> Is there any convenient API to obtain a MemorySegment of the nth array element? Currently I'm calculating memory boundaries manually and slice my segment accordingly:
>>>
>>> ```
>>> private void upcall(MemoryAddress pointer) {
>>>     try (var scope = ResourceScope.newConfinedScope()) {
>>>        var structLayout = ...;
>>>        var sequenceLayout = MemoryLayout.sequenceLayout(42, structLayout);
>>>        var segment = MemorySegment.ofAddress(pointer, sequenceLayout.byteSize(), scope);
>>>
>>>        // either:
>>>        var offset0 = sequenceLayout.byteOffset(MemoryLayout.PathElement.sequenceElement(0));
>>>        var offset1 = sequenceLayout.byteOffset(MemoryLayout.PathElement.sequenceElement(1));
>>>        var elem0 = segment.asSlice(offset0, structLayout.byteSize());
>>>        var elem1 = segment.asSlice(offset1, structLayout.byteSize());
>>>
>>>        // or alternatively:
>>>        var elem0 = segment.asSlice(0, structLayout.byteSize());
>>>        var elem1 = segment.asSlice(structLayout.byteSize(), structLayout.byteSize());
>>>     }
>>> }
>>> ```
>>>
>>> But since a SequenceLayout knows how to calculate the offset and knows the size of each of its elements, I guess there is a more convenient way to slice a segment.
>>>
>>> Or if there isn't: Consider this a feature request ��
>>>
>>> Cheers!
>>> Sebastian
>>>
>>> [1]: https://urldefense.com/v3/__https://github.com/skymatic/fuse-panama/blob/develop/mac/src/main/java/de/skymatic/fusepanama/mac/MacFuseOperationsMapper.java*L178-L187__;Iw!!ACWV5N9M2RV99hQ!Zkw2UevH7tHtVRCVOw26fKKMnrSXW14_OkGwUxlfVh6CLFkmHDIojtxtBeCOUKEzyHR6cfU$


More information about the panama-dev mailing list