RFC: static bulk copy methods

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Jun 10 14:28:08 UTC 2021


Hi
I've create a draft PR which adds the new MemorySegment method to do the 
bulk copy (with swap if needed), plus the code that Lee posted in this 
thread [1]:

https://github.com/openjdk/panama-foreign/pull/555

There are a couple of points which deserve a discussion.

First, array indices are always expressed as logical indices (e.g. to 
access the second long in a long[], we use "1", not "16"). This creates 
some tension when adding the static methods for doing the bulk copy 
between arrays and segments, as the more natural index to be used with a 
segment is not a logical index, but just a raw byte offset. In this PR 
the static methods in MemoryCopy simply accept logical indices for 
arrays and raw offsets for segments, w/o any further attempt to 
reconcile the mismatch. In a separate thread [2] we have discussed few 
options to ameliorate the situation, should this become an issue in real 
code.

Second, to do a "swappy" bulk copy we need to know the size of the 
elements we're copying. That's because the byte swap will be applied on 
a per-element basis (of course). There are several options to provide 
such an API in MemorySegment, listed below:

```
MemorySegment.copyFrom(MemorySegment src, int elemSize, boolean swap) // 1
MemorySegment.copyFrom(MemorySegment src, ValueLayout elemLayout, 
ByteOrder order) // 2
MemorySegment.copyFrom(MemorySegment src, ValueLayout srcElementLayout, 
ValueLayout dstElementLayout) // 3
```

The first is merely a wrapper around unsafe. It's a good fallback, but 
seems very low level, even for our API; specifically, it seems we could 
do something to avoid that "swap" parameter.

The second option takes a step towards layouts - e.g. if we model 
elements with a layout, then we can compare the endianness of the layout 
with the provided order. What I find confusing about this API is that 
it's not clear to which segment (source or target) does the layout or 
order arguments apply to.

The third option fully embrace layouts and is what is implemented in the 
PR. We now have a layout for the source elements, and a layout for the 
destination elements. If their order is different a byte swap occurs. 
The simpler one-argument copyFrom can be expressed as:

```
copyFrom(src) == copyFrom(src, JAVA_BYTE, JAVA_BYTE)
```

To perform a swappy copy between short elements, a client would probably do:

```
copyFrom(src, BITS_16_LE, BITS_16_BE)
```

The method will also check alignment constraints in the source and 
target segments, so if clients want to use this enhanced copyFrom to 
copy elements at unaligned addresses, the alignment constraints should 
be removed from the target layout:

```
copyFrom(src, BITS_16_LE, BITS_16_BE.withBitAlignment(8))
```

This check adds extra safety belts, and does not affect expressiveness, 
since we can always create "unaligned" layouts to bulk copy at arbitrary 
addresses --- and I imagine that the routines in MemoryCopy will want to 
do something along these lines.

Comments welcome.

Maurizio

[1] - 
https://mail.openjdk.java.net/pipermail/panama-dev/2021-April/013518.html
[2] - 
https://mail.openjdk.java.net/pipermail/panama-dev/2021-June/014047.html


More information about the panama-dev mailing list