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