[foreign] RFR: 8226555: Provide java.foreign.memory.Array a copy function similar to System.arraycopy
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Jun 21 07:46:12 UTC 2019
Hi Henry,
I'm unsure about the approach.
We have this routine sitting in BoundedPointer.java:
public static <Z> BoundedPointer<Z> fromArray(LayoutType<Z> type, Object array) {
254 int size = java.lang.reflect.Array.getLength(array);
255 long base = Util.unsafeArrayBase(array.getClass());
256 long scale = Util.unsafeArrayScale(array.getClass());
257 return new BoundedPointer<>(type, ScopeImpl.UNCHECKED, AccessMode.READ_WRITE,
258 MemoryBoundInfo.ofHeap(array, base, size * scale));
259 }
If this became a new static factory on Pointer, then surely you could
convert the Java array into a pointer and then use Pointer.copy for all
the things you want to do?
The copyTo/From methods and Array::assign where really born not to copy
stuff, but to initialize a native array (hence the strict length
requirement), or to assign an array to a struct field (of same type).
Note that the two public Array::assign methods (for Java to native,
native to Java) were added later, in response to some (valid!)
performance concern, so they are more an example of what the impl can
do, rather than a case of a perfectly designed API.
I believe we should:
1) keep Array::assign to mimic C assign between array in struct fields
2) drop the Array::assign between Java vs. native and viceversa
3) add a supported way to create a (heap) Pointer from a Java array -
after all we can create Pointer from bytebuffer so I don't see why we
shouldn't allow the same for arrays
This way you can use the existing Pointer.copy API instead of the
'hybrid' Array::assign methods.
As for copying when layout is not the same, pointer.copy will fail - and
I think it should continue to do so - user can cast his/her way around
that. Don't be fooled by the fact that BoundedArray::copyFrom/To has a
slow path - again, those routines are for (i) initializing the contents
of a native array from a Java array or (ii) dumping the contents of a
native array onto a Java array - so the slow path was originally added
to handle cases where the LayoutType was 'complex' and required manual
adaptation of the contents.
P.S.
as for your overload question, I think all the new methods are ambiguous
- because when you call them, a numeric constant such as '0' is
interpreted as 'int' and is compatible with both 'int' and 'long'. So
it's a bit like doing:
m(int i, long l)
m(long l, int i)
m(long l1, long l2)
m(0, 0)
which is ambiguous. In your case is a bit more complex, as you have
another ambiguity going on, between Object and Array, but that one could
resolved correctly, if it weren't for the long vs. int mismatches, which
make the three methods fundamentally incompatible with each other, with
no 'best' one (if you pass ints). What you'd really need to resolve the
ambiguity would be a method with signature:
(Array, int, Array, int, int)
Which would be more specific than both - but of course in this case,
this signature doesn't make sense.
Maurizio
On 21/06/2019 07:59, Henry Jen wrote:
> Hi,
>
> Please review a webrev[1] to provide more flexible way to copy between native and native/java arrays.
>
> This webrev changes Array.assign behavior to make it more consistent:
>
> 1. It add a slow-path copy for assign between native arrays. Given the carrier type is the same, in case the native layout doesn’t match, it can fallback to sequential copy, which have been available for assign between native and java arrays.
>
> 2. It allows copy source array in full to a larger destination array. Before the patch, only slow path between native and java array can do that. Otherwise, it will have IllegalArgumentException caused by different layout.
>
> This webrev make assign work consistently between all three modes so that, it will copy full source array into destination that is large enough, or throw IndexOutOfBoundException if the destination is too small.
>
> Do check out the test case, that would help to clarify the specs if it’s not clear enough.
>
> There is a minor irritation for the API in that, it can be ambiguous between Array and Object, as you can see following example.
>
> /Users/hjen/ws/panama.dev/test/jdk/java/foreign/memory/ArrayTest.java:360: error: reference to copy is ambiguous
> Array.copy(EMPTY_INT_ARRAY, 0, naInt, 0, 0);
> ^
> both method <Z#1>copy(Array<Z#1>,long,Object,int,int) in Array and method <Z#2>copy(Object,int,Array<Z#2>,long,int) in Array match
> where Z#1,Z#2 are type-variables:
> Z#1 extends Object declared in method <Z#1>copy(Array<Z#1>,long,Object,int,int)
> Z#2 extends Object declared in method <Z#2>copy(Object,int,Array<Z#2>,long,int)
>
> I am not sure why javac pick those two, while I actually want the third one,
>
> copy(Array<Z>, long, Array<Z>, long, long);
>
> A simple fix is simply to cast the last argument.
> Array.copy(EMPTY_INT_ARRAY, 0, naInt, 0, 0L);
>
> Perhaps we can simply rename cop between Array to copyNative or something. Suggestions?
>
> Cheers,
> Henry
>
> [1] http://cr.openjdk.java.net/~henryjen/panama/8226555/0/webrev/
More information about the panama-dev
mailing list