1 /* 2 * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @run testng TestArrayCopy 27 */ 28 29 import java.lang.foreign.MemoryLayout; 30 import java.lang.foreign.MemorySegment; 31 import java.lang.foreign.ValueLayout; 32 import java.lang.invoke.MethodHandle; 33 import java.lang.invoke.MethodHandles; 34 import java.lang.invoke.MethodType; 35 import java.lang.invoke.VarHandle; 36 import java.nio.ByteOrder; 37 import java.util.ArrayList; 38 import java.util.List; 39 import org.testng.annotations.DataProvider; 40 import org.testng.annotations.Test; 41 42 import static java.lang.foreign.ValueLayout.JAVA_BYTE; 43 import static java.lang.foreign.ValueLayout.JAVA_INT; 44 import static org.testng.Assert.assertEquals; 45 import static org.testng.Assert.fail; 46 47 /** 48 * These tests exercise the MemoryCopy copyFromArray(...) and copyToArray(...). 49 * To make these tests more challenging the segment is a view of the given array, 50 * which makes the copy operations overlapping self-copies. Thus, this checks the claim: 51 * 52 * <p>If the source (destination) segment is actually a view of the destination (source) array, 53 * and if the copy region of the source overlaps with the copy region of the destination, 54 * the copy of the overlapping region is performed as if the data in the overlapping region 55 * were first copied into a temporary segment before being copied to the destination.</p> 56 */ 57 public class TestArrayCopy { 58 private static final ByteOrder NATIVE_ORDER = ByteOrder.nativeOrder(); 59 private static final ByteOrder NON_NATIVE_ORDER = NATIVE_ORDER == ByteOrder.LITTLE_ENDIAN 60 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; 61 62 private static final int SEG_LENGTH_BYTES = 32; 63 private static final int SEG_OFFSET_BYTES = 8; 64 65 @Test(dataProvider = "copyModesAndHelpers") 66 public void testSelfCopy(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { 67 int bytesPerElement = (int)helper.elementLayout.byteSize(); 68 int indexShifts = SEG_OFFSET_BYTES / bytesPerElement; 69 MemorySegment base = srcSegment(SEG_LENGTH_BYTES); 70 MemorySegment truth = truthSegment(base, helper, indexShifts, mode); 71 ByteOrder bo = mode.swap ? NON_NATIVE_ORDER : NATIVE_ORDER; 72 //CopyFrom 73 Object srcArr = helper.toArray(base); 74 int srcIndex = mode.direction ? 0 : indexShifts; 75 int srcCopyLen = helper.length(srcArr) - indexShifts; 76 MemorySegment dstSeg = helper.fromArray(srcArr); 77 long dstOffsetBytes = mode.direction ? SEG_OFFSET_BYTES : 0; 78 helper.copyFromArray(srcArr, srcIndex, srcCopyLen, dstSeg, dstOffsetBytes, bo); 79 assertEquals(truth.mismatch(dstSeg), -1); 80 //CopyTo 81 long srcOffsetBytes = mode.direction ? 0 : SEG_OFFSET_BYTES; 82 Object dstArr = helper.toArray(base); 83 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); 84 int dstIndex = mode.direction ? indexShifts : 0; 85 int dstCopyLen = helper.length(dstArr) - indexShifts; 86 helper.copyToArray(srcSeg, srcOffsetBytes, dstArr, dstIndex, dstCopyLen, bo); 87 MemorySegment result = helper.fromArray(dstArr); 88 assertEquals(truth.mismatch(result), -1); 89 } 90 91 @Test(dataProvider = "copyModesAndHelpers") 92 public void testUnalignedCopy(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { 93 int bytesPerElement = (int)helper.elementLayout.byteSize(); 94 int indexShifts = SEG_OFFSET_BYTES / bytesPerElement; 95 MemorySegment base = srcSegment(SEG_LENGTH_BYTES); 96 ByteOrder bo = mode.swap ? NON_NATIVE_ORDER : NATIVE_ORDER; 97 //CopyFrom 98 Object srcArr = helper.toArray(base); 99 int srcIndex = mode.direction ? 0 : indexShifts; 100 int srcCopyLen = helper.length(srcArr) - indexShifts; 101 MemorySegment dstSeg = helper.fromArray(srcArr); 102 long dstOffsetBytes = mode.direction ? (SEG_OFFSET_BYTES - 1) : 0; 103 helper.copyFromArray(srcArr, srcIndex, srcCopyLen, dstSeg, dstOffsetBytes, bo); 104 //CopyTo 105 long srcOffsetBytes = mode.direction ? 0 : (SEG_OFFSET_BYTES - 1); 106 Object dstArr = helper.toArray(base); 107 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); 108 int dstIndex = mode.direction ? indexShifts : 0; 109 int dstCopyLen = helper.length(dstArr) - indexShifts; 110 helper.copyToArray(srcSeg, srcOffsetBytes, dstArr, dstIndex, dstCopyLen, bo); 111 } 112 113 @Test(dataProvider = "copyModesAndHelpers") 114 public void testCopyOobLength(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { 115 int bytesPerElement = (int)helper.elementLayout.byteSize(); 116 MemorySegment base = srcSegment(SEG_LENGTH_BYTES); 117 //CopyFrom 118 Object srcArr = helper.toArray(base); 119 MemorySegment dstSeg = helper.fromArray(srcArr); 120 try { 121 helper.copyFromArray(srcArr, 0, (SEG_LENGTH_BYTES / bytesPerElement) * 2, dstSeg, 0, ByteOrder.nativeOrder()); 122 fail(); 123 } catch (IndexOutOfBoundsException ex) { 124 //ok 125 } 126 //CopyTo 127 Object dstArr = helper.toArray(base); 128 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); 129 try { 130 helper.copyToArray(srcSeg, 0, dstArr, 0, (SEG_LENGTH_BYTES / bytesPerElement) * 2, ByteOrder.nativeOrder()); 131 fail(); 132 } catch (IndexOutOfBoundsException ex) { 133 //ok 134 } 135 } 136 137 @Test(dataProvider = "copyModesAndHelpers") 138 public void testCopyNegativeIndices(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { 139 int bytesPerElement = (int)helper.elementLayout.byteSize(); 140 MemorySegment base = srcSegment(SEG_LENGTH_BYTES); 141 //CopyFrom 142 Object srcArr = helper.toArray(base); 143 MemorySegment dstSeg = helper.fromArray(srcArr); 144 try { 145 helper.copyFromArray(srcArr, -1, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder()); 146 fail(); 147 } catch (IndexOutOfBoundsException ex) { 148 //ok 149 } 150 //CopyTo 151 Object dstArr = helper.toArray(base); 152 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); 153 try { 154 helper.copyToArray(srcSeg, 0, dstArr, -1, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder()); 155 fail(); 156 } catch (IndexOutOfBoundsException ex) { 157 //ok 158 } 159 } 160 161 @Test(dataProvider = "copyModesAndHelpers") 162 public void testCopyNegativeOffsets(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { 163 int bytesPerElement = (int)helper.elementLayout.byteSize(); 164 MemorySegment base = srcSegment(SEG_LENGTH_BYTES); 165 //CopyFrom 166 Object srcArr = helper.toArray(base); 167 MemorySegment dstSeg = helper.fromArray(srcArr); 168 try { 169 helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, -1, ByteOrder.nativeOrder()); 170 fail(); 171 } catch (IndexOutOfBoundsException ex) { 172 //ok 173 } 174 //CopyTo 175 Object dstArr = helper.toArray(base); 176 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); 177 try { 178 helper.copyToArray(srcSeg, -1, dstArr, 0, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder()); 179 fail(); 180 } catch (IndexOutOfBoundsException ex) { 181 //ok 182 } 183 } 184 185 @Test(dataProvider = "copyModesAndHelpers") 186 public void testCopyOobIndices(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { 187 int bytesPerElement = (int)helper.elementLayout.byteSize(); 188 MemorySegment base = srcSegment(SEG_LENGTH_BYTES); 189 //CopyFrom 190 Object srcArr = helper.toArray(base); 191 MemorySegment dstSeg = helper.fromArray(srcArr); 192 try { 193 helper.copyFromArray(srcArr, helper.length(srcArr) + 1, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder()); 194 fail(); 195 } catch (IndexOutOfBoundsException ex) { 196 //ok 197 } 198 //CopyTo 199 Object dstArr = helper.toArray(base); 200 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); 201 try { 202 helper.copyToArray(srcSeg, 0, dstArr, helper.length(dstArr) + 1, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder()); 203 fail(); 204 } catch (IndexOutOfBoundsException ex) { 205 //ok 206 } 207 } 208 209 @Test(dataProvider = "copyModesAndHelpers") 210 public void testCopyOobOffsets(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { 211 int bytesPerElement = (int)helper.elementLayout.byteSize(); 212 MemorySegment base = srcSegment(SEG_LENGTH_BYTES); 213 //CopyFrom 214 Object srcArr = helper.toArray(base); 215 MemorySegment dstSeg = helper.fromArray(srcArr); 216 try { 217 helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, SEG_LENGTH_BYTES + 1, ByteOrder.nativeOrder()); 218 fail(); 219 } catch (IndexOutOfBoundsException ex) { 220 //ok 221 } 222 //CopyTo 223 Object dstArr = helper.toArray(base); 224 MemorySegment srcSeg = helper.fromArray(dstArr).asReadOnly(); 225 try { 226 helper.copyToArray(srcSeg, SEG_OFFSET_BYTES + 1, dstArr, 0, SEG_LENGTH_BYTES / bytesPerElement, ByteOrder.nativeOrder()); 227 fail(); 228 } catch (IndexOutOfBoundsException ex) { 229 //ok 230 } 231 } 232 233 @Test(dataProvider = "copyModesAndHelpers") 234 public void testCopyReadOnlyDest(CopyMode mode, CopyHelper<Object, ValueLayout> helper, String helperDebugString) { 235 int bytesPerElement = (int)helper.elementLayout.byteSize(); 236 MemorySegment base = srcSegment(SEG_LENGTH_BYTES); 237 //CopyFrom 238 Object srcArr = helper.toArray(base); 239 MemorySegment dstSeg = helper.fromArray(srcArr).asReadOnly(); 240 try { 241 helper.copyFromArray(srcArr, 0, SEG_LENGTH_BYTES / bytesPerElement, dstSeg, 0, ByteOrder.nativeOrder()); 242 fail(); 243 } catch (UnsupportedOperationException ex) { 244 //ok 245 } 246 } 247 248 @Test(expectedExceptions = IllegalArgumentException.class) 249 public void testNotAnArraySrc() { 250 MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); 251 MemorySegment.copy(segment, JAVA_BYTE, 0, new String[] { "hello" }, 0, 4); 252 } 253 254 @Test(expectedExceptions = IllegalArgumentException.class) 255 public void testNotAnArrayDst() { 256 MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); 257 MemorySegment.copy(new String[] { "hello" }, 0, segment, JAVA_BYTE, 0, 4); 258 } 259 260 @Test(expectedExceptions = IllegalArgumentException.class) 261 public void testCarrierMismatchSrc() { 262 MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); 263 MemorySegment.copy(segment, JAVA_INT, 0, new byte[] { 1, 2, 3, 4 }, 0, 4); 264 } 265 266 @Test(expectedExceptions = IllegalArgumentException.class) 267 public void testCarrierMismatchDst() { 268 MemorySegment segment = MemorySegment.ofArray(new int[] {1, 2, 3, 4}); 269 MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_INT, 0, 4); 270 } 271 272 @Test(expectedExceptions = IllegalArgumentException.class) 273 public void testHyperAlignedSrc() { 274 MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); 275 MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_BYTE.withByteAlignment(2), 0, 4); 276 } 277 278 @Test(expectedExceptions = IllegalArgumentException.class) 279 public void testHyperAlignedDst() { 280 MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); 281 MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, new byte[] { 1, 2, 3, 4 }, 0, 4); 282 } 283 284 /***** Utilities *****/ 285 286 public static MemorySegment srcSegment(int bytesLength) { 287 byte[] arr = new byte[bytesLength]; 288 for (int i = 0; i < arr.length; i++) { 289 arr[i] = (byte)i; 290 } 291 return MemorySegment.ofArray(arr); 292 } 293 294 private static VarHandle arrayVarHandle(ValueLayout layout) { 295 return MethodHandles.collectCoordinates(layout.varHandle(), 296 1, MethodHandles.insertArguments(layout.scaleHandle(), 0, 0L)); 297 } 298 299 public static MemorySegment truthSegment(MemorySegment srcSeg, CopyHelper<?, ?> helper, int indexShifts, CopyMode mode) { 300 VarHandle indexedHandleNO = arrayVarHandle(helper.elementLayout.withOrder(NATIVE_ORDER)); 301 VarHandle indexedHandleNNO = arrayVarHandle(helper.elementLayout.withOrder(NON_NATIVE_ORDER)); 302 MemorySegment dstSeg = MemorySegment.ofArray(srcSeg.toArray(JAVA_BYTE)); 303 int indexLength = (int) dstSeg.byteSize() / (int)helper.elementLayout.byteSize(); 304 if (mode.direction) { 305 if (mode.swap) { 306 for (int i = indexLength - 1; i >= indexShifts; i--) { 307 Object v = indexedHandleNNO.get(dstSeg, i - indexShifts); 308 indexedHandleNO.set(dstSeg, i, v); 309 } 310 } else { 311 for (int i = indexLength - 1; i >= indexShifts; i--) { 312 Object v = indexedHandleNO.get(dstSeg, i - indexShifts); 313 indexedHandleNO.set(dstSeg, i, v); 314 } 315 } 316 } else { //down 317 if (mode.swap) { 318 for (int i = indexShifts; i < indexLength; i++) { 319 Object v = indexedHandleNNO.get(dstSeg, i); 320 indexedHandleNO.set(dstSeg, i - indexShifts, v); 321 } 322 } else { 323 for (int i = indexShifts; i < indexLength; i++) { 324 Object v = indexedHandleNO.get(dstSeg, i); 325 indexedHandleNO.set(dstSeg, i - indexShifts, v); 326 } 327 } 328 } 329 return dstSeg; 330 } 331 332 enum CopyMode { 333 UP_NO_SWAP(true, false), 334 UP_SWAP(true, true), 335 DOWN_NO_SWAP(false, false), 336 DOWN_SWAP(false, true); 337 338 final boolean direction; 339 final boolean swap; 340 341 CopyMode(boolean direction, boolean swap) { 342 this.direction = direction; 343 this.swap = swap; 344 } 345 } 346 347 abstract static class CopyHelper<X, L extends ValueLayout> { 348 349 final L elementLayout; 350 final Class<?> carrier; 351 352 @SuppressWarnings("unchecked") 353 public CopyHelper(L elementLayout, Class<X> carrier) { 354 this.elementLayout = (L)elementLayout.withByteAlignment(1); 355 this.carrier = carrier; 356 } 357 358 abstract void copyFromArray(X srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo); 359 abstract void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, X dstArr, int dstIndex, int dstCopyLen, ByteOrder bo); 360 abstract X toArray(MemorySegment segment); 361 abstract MemorySegment fromArray(X array); 362 abstract int length(X arr); 363 364 @Override 365 public String toString() { 366 return "CopyHelper{" + 367 "elementLayout=" + elementLayout + 368 ", carrier=" + carrier.getName() + 369 '}'; 370 } 371 372 static final CopyHelper<byte[], ValueLayout.OfByte> BYTE = new CopyHelper<>(JAVA_BYTE, byte[].class) { 373 @Override 374 void copyFromArray(byte[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 375 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 376 } 377 378 @Override 379 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, byte[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 380 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 381 } 382 383 @Override 384 byte[] toArray(MemorySegment segment) { 385 return segment.toArray(elementLayout); 386 } 387 388 @Override 389 MemorySegment fromArray(byte[] array) { 390 return MemorySegment.ofArray(array); 391 } 392 393 @Override 394 int length(byte[] arr) { 395 return arr.length; 396 } 397 }; 398 399 static final CopyHelper<char[], ValueLayout.OfChar> CHAR = new CopyHelper<>(ValueLayout.JAVA_CHAR, char[].class) { 400 @Override 401 void copyFromArray(char[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 402 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 403 } 404 405 @Override 406 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, char[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 407 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 408 } 409 410 @Override 411 char[] toArray(MemorySegment segment) { 412 return segment.toArray(elementLayout); 413 } 414 415 @Override 416 MemorySegment fromArray(char[] array) { 417 return MemorySegment.ofArray(array); 418 } 419 420 @Override 421 int length(char[] arr) { 422 return arr.length; 423 } 424 }; 425 426 static final CopyHelper<short[], ValueLayout.OfShort> SHORT = new CopyHelper<>(ValueLayout.JAVA_SHORT, short[].class) { 427 @Override 428 void copyFromArray(short[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 429 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 430 } 431 432 @Override 433 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, short[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 434 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 435 } 436 437 @Override 438 short[] toArray(MemorySegment segment) { 439 return segment.toArray(elementLayout); 440 } 441 442 @Override 443 MemorySegment fromArray(short[] array) { 444 return MemorySegment.ofArray(array); 445 } 446 447 @Override 448 int length(short[] arr) { 449 return arr.length; 450 } 451 }; 452 453 static final CopyHelper<int[], ValueLayout.OfInt> INT = new CopyHelper<>(ValueLayout.JAVA_INT, int[].class) { 454 @Override 455 void copyFromArray(int[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 456 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 457 } 458 459 @Override 460 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, int[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 461 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 462 } 463 464 @Override 465 int[] toArray(MemorySegment segment) { 466 return segment.toArray(elementLayout); 467 } 468 469 @Override 470 MemorySegment fromArray(int[] array) { 471 return MemorySegment.ofArray(array); 472 } 473 474 @Override 475 int length(int[] arr) { 476 return arr.length; 477 } 478 }; 479 480 static final CopyHelper<float[], ValueLayout.OfFloat> FLOAT = new CopyHelper<>(ValueLayout.JAVA_FLOAT, float[].class) { 481 @Override 482 void copyFromArray(float[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 483 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 484 } 485 486 @Override 487 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, float[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 488 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 489 } 490 491 @Override 492 float[] toArray(MemorySegment segment) { 493 return segment.toArray(elementLayout); 494 } 495 496 @Override 497 MemorySegment fromArray(float[] array) { 498 return MemorySegment.ofArray(array); 499 } 500 501 @Override 502 int length(float[] arr) { 503 return arr.length; 504 } 505 }; 506 507 static final CopyHelper<long[], ValueLayout.OfLong> LONG = new CopyHelper<>(ValueLayout.JAVA_LONG, long[].class) { 508 @Override 509 void copyFromArray(long[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 510 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 511 } 512 513 @Override 514 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, long[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 515 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 516 } 517 518 @Override 519 long[] toArray(MemorySegment segment) { 520 return segment.toArray(elementLayout); 521 } 522 523 @Override 524 MemorySegment fromArray(long[] array) { 525 return MemorySegment.ofArray(array); 526 } 527 528 @Override 529 int length(long[] arr) { 530 return arr.length; 531 } 532 }; 533 534 static final CopyHelper<double[], ValueLayout.OfDouble> DOUBLE = new CopyHelper<>(ValueLayout.JAVA_DOUBLE, double[].class) { 535 @Override 536 void copyFromArray(double[] srcArr, int srcIndex, int srcCopyLen, MemorySegment dstSeg, long dstOffsetBytes, ByteOrder bo) { 537 MemorySegment.copy(srcArr, srcIndex, dstSeg, elementLayout.withOrder(bo), dstOffsetBytes, srcCopyLen); 538 } 539 540 @Override 541 void copyToArray(MemorySegment srcSeg, long srcOffsetBytes, double[] dstArr, int dstIndex, int dstCopyLen, ByteOrder bo) { 542 MemorySegment.copy(srcSeg, elementLayout.withOrder(bo), srcOffsetBytes, dstArr, dstIndex, dstCopyLen); 543 } 544 545 @Override 546 double[] toArray(MemorySegment segment) { 547 return segment.toArray(elementLayout); 548 } 549 550 @Override 551 MemorySegment fromArray(double[] array) { 552 return MemorySegment.ofArray(array); 553 } 554 555 @Override 556 int length(double[] arr) { 557 return arr.length; 558 } 559 }; 560 } 561 562 @DataProvider 563 Object[][] copyModesAndHelpers() { 564 CopyHelper<?, ?>[] helpers = { CopyHelper.BYTE, CopyHelper.CHAR, CopyHelper.SHORT, CopyHelper.INT, 565 CopyHelper.FLOAT, CopyHelper.LONG, CopyHelper.DOUBLE }; 566 List<Object[]> results = new ArrayList<>(); 567 for (CopyHelper<?, ?> helper : helpers) { 568 for (CopyMode mode : CopyMode.values()) { 569 results.add(new Object[] { mode, helper, helper.toString() }); 570 } 571 } 572 return results.stream().toArray(Object[][]::new); 573 } 574 }