1 /*
  2  * Copyright (c) 2020, 2023, 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 /*
 26  * @test
 27  * @modules java.base/jdk.internal.foreign
 28  * @run testng/othervm TestSegmentAllocators
 29  */
 30 
 31 import java.lang.foreign.*;
 32 
 33 import jdk.internal.foreign.NativeMemorySegmentImpl;
 34 import org.testng.annotations.*;
 35 
 36 import java.lang.foreign.Arena;
 37 import java.lang.invoke.VarHandle;
 38 import java.nio.ByteBuffer;
 39 import java.nio.ByteOrder;
 40 import java.nio.CharBuffer;
 41 import java.nio.DoubleBuffer;
 42 import java.nio.FloatBuffer;
 43 import java.nio.IntBuffer;
 44 import java.nio.LongBuffer;
 45 import java.nio.ShortBuffer;
 46 import java.util.ArrayList;
 47 import java.util.List;
 48 import java.util.concurrent.atomic.AtomicInteger;
 49 import java.util.function.BiFunction;
 50 import java.util.function.Function;
 51 
 52 import static org.testng.Assert.*;
 53 
 54 public class TestSegmentAllocators {
 55 
 56     final static int ELEMS = 128;
 57 
 58     @Test(dataProvider = "scalarAllocations")
 59     @SuppressWarnings("unchecked")
 60     public <Z, L extends ValueLayout> void testAllocation(Z value, AllocationFactory allocationFactory, L layout, AllocationFunction<Z, L> allocationFunction, Function<MemoryLayout, VarHandle> handleFactory) {
 61         layout = (L)layout.withByteAlignment(layout.byteSize());
 62         L[] layouts = (L[])new ValueLayout[] {
 63                 layout,
 64                 layout.withByteAlignment(layout.byteAlignment() * 2),
 65                 layout.withByteAlignment(layout.byteAlignment() * 4),
 66                 layout.withByteAlignment(layout.byteAlignment() * 8)
 67         };
 68         for (L alignedLayout : layouts) {
 69             List<MemorySegment> addressList = new ArrayList<>();
 70             int elems = ELEMS / ((int)alignedLayout.byteAlignment() / (int)layout.byteAlignment());
 71             Arena[] arenas = {
 72                     Arena.ofConfined(),
 73                     Arena.ofShared()
 74             };
 75             for (Arena arena : arenas) {
 76                 try (arena) {
 77                     SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, arena);
 78                     for (int i = 0; i < elems; i++) {
 79                         MemorySegment address = allocationFunction.allocate(allocator, alignedLayout, value);
 80                         assertEquals(address.byteSize(), alignedLayout.byteSize());
 81                         addressList.add(address);
 82                         VarHandle handle = handleFactory.apply(alignedLayout);
 83                         assertEquals(value, handle.get(address, 0L));
 84                     }
 85                     boolean isBound = allocationFactory.isBound();
 86                     try {
 87                         allocationFunction.allocate(allocator, alignedLayout, value);
 88                         assertFalse(isBound);
 89                     } catch (IndexOutOfBoundsException ex) {
 90                         //failure is expected if bound
 91                         assertTrue(isBound);
 92                     }
 93                 }
 94                 // addresses should be invalid now
 95                 for (MemorySegment address : addressList) {
 96                     assertFalse(address.scope().isAlive());
 97                 }
 98             }
 99         }
100     }
101 
102     static final int SIZE_256M = 1024 * 1024 * 256;
103 
104     @Test
105     public void testBigAllocationInUnboundedSession() {
106         try (Arena arena = Arena.ofConfined()) {
107             for (int i = 8 ; i < SIZE_256M ; i *= 8) {
108                 SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(i * 2 + 1));
109                 MemorySegment address = allocator.allocate(i, i);
110                 //check size
111                 assertEquals(address.byteSize(), i);
112                 //check alignment
113                 assertEquals(address.address() % i, 0);
114             }
115         }
116     }
117 
118     @Test
119     public void testTooBigForBoundedArena() {
120         try (Arena arena = Arena.ofConfined()) {
121             SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(10));
122             assertThrows(IndexOutOfBoundsException.class, () -> allocator.allocate(12));
123             allocator.allocate(5);
124         }
125     }
126 
127     @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
128     public void testBadAllocationSize(SegmentAllocator allocator) {
129         allocator.allocate(-1);
130     }
131 
132     @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
133     public void testBadAllocationAlignZero(SegmentAllocator allocator) {
134         allocator.allocate(1, 0);
135     }
136 
137     @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
138     public void testBadAllocationAlignNeg(SegmentAllocator allocator) {
139         allocator.allocate(1, -1);
140     }
141 
142     @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
143     public void testBadAllocationAlignNotPowerTwo(SegmentAllocator allocator) {
144         allocator.allocate(1, 3);
145     }
146 
147     @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
148     public void testBadAllocationArrayNegSize(SegmentAllocator allocator) {
149         allocator.allocate(ValueLayout.JAVA_BYTE, -1);
150     }
151 
152     @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
153     public void testBadAllocationArrayOverflow(SegmentAllocator allocator) {
154         allocator.allocate(ValueLayout.JAVA_LONG,  Long.MAX_VALUE);
155     }
156 
157     @Test(expectedExceptions = OutOfMemoryError.class)
158     public void testBadArenaNullReturn() {
159         try (Arena arena = Arena.ofConfined()) {
160             arena.allocate(Long.MAX_VALUE, 2);
161         }
162     }
163 
164     @Test
165     public void testArrayAllocateDelegation() {
166         AtomicInteger calls = new AtomicInteger();
167         SegmentAllocator allocator = new SegmentAllocator() {
168             @Override
169             public MemorySegment allocate(long bytesSize, long byteAlignment) {
170                 return MemorySegment.NULL;
171             }
172 
173             @Override
174             public MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source, ValueLayout sourceElementLayout, long sourceOffset, long elementCount) {
175                 calls.incrementAndGet();
176                 return MemorySegment.NULL;
177             }
178         };
179         allocator.allocateFrom(ValueLayout.JAVA_BYTE);
180         allocator.allocateFrom(ValueLayout.JAVA_SHORT);
181         allocator.allocateFrom(ValueLayout.JAVA_CHAR);
182         allocator.allocateFrom(ValueLayout.JAVA_INT);
183         allocator.allocateFrom(ValueLayout.JAVA_FLOAT);
184         allocator.allocateFrom(ValueLayout.JAVA_LONG);
185         allocator.allocateFrom(ValueLayout.JAVA_DOUBLE);
186         assertEquals(calls.get(), 7);
187     }
188 
189     @Test
190     public void testStringAllocateDelegation() {
191         AtomicInteger calls = new AtomicInteger();
192         SegmentAllocator allocator = new SegmentAllocator() {
193             @Override
194             public MemorySegment allocate(long byteSize, long byteAlignment) {
195                 return Arena.ofAuto().allocate(byteSize, byteAlignment);
196             }
197 
198             @Override
199             public MemorySegment allocate(long size) {
200                 calls.incrementAndGet();
201                 return allocate(size, 1);
202             };
203         };
204         allocator.allocateFrom("Hello");
205         assertEquals(calls.get(), 1);
206     }
207 
208 
209     @Test(dataProvider = "arrayAllocations")
210     public <Z> void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Object, ValueLayout> allocationFunction, ToArrayHelper<Z> arrayHelper) {
211         Z arr = arrayHelper.array();
212         Arena[] arenas = {
213                 Arena.ofConfined(),
214                 Arena.ofShared()
215         };
216         for (Arena arena : arenas) {
217             try (arena) {
218                 SegmentAllocator allocator = allocationFactory.allocator(100, arena);
219                 MemorySegment address = allocationFunction.allocate(allocator, layout, arr);
220                 Z found = arrayHelper.toArray(address, layout);
221                 assertEquals(found, arr);
222             }
223         }
224     }
225 
226     @Test(dataProvider = "arrayAllocations")
227     public <Z> void testPredicatesAndCommands(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Object, ValueLayout> allocationFunction, ToArrayHelper<Z> arrayHelper) {
228         Z arr = arrayHelper.array();
229         Arena[] arenas = {
230                 Arena.ofConfined(),
231                 Arena.ofShared()
232         };
233         for (Arena arena : arenas) {
234             try (arena) {
235                 SegmentAllocator allocator = allocationFactory.allocator(100, arena);
236                 MemorySegment segment = allocationFunction.allocate(allocator, layout, arr);
237                 assertThrows(UnsupportedOperationException.class, segment::load);
238                 assertThrows(UnsupportedOperationException.class, segment::unload);
239                 assertThrows(UnsupportedOperationException.class, segment::isLoaded);
240                 assertThrows(UnsupportedOperationException.class, segment::force);
241                 assertFalse(segment.isMapped());
242                 assertEquals(segment.isNative(), segment instanceof NativeMemorySegmentImpl);
243             }
244         }
245     }
246 
247     @DataProvider(name = "scalarAllocations")
248     static Object[][] scalarAllocations() {
249         List<Object[]> scalarAllocations = new ArrayList<>();
250         for (AllocationFactory factory : AllocationFactory.values()) {
251             scalarAllocations.add(new Object[] { (byte)42, factory, ValueLayout.JAVA_BYTE,
252                     (AllocationFunction.OfByte) SegmentAllocator::allocateFrom,
253                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
254             scalarAllocations.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN),
255                     (AllocationFunction.OfShort) SegmentAllocator::allocateFrom,
256                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
257             scalarAllocations.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN),
258                     (AllocationFunction.OfChar) SegmentAllocator::allocateFrom,
259                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
260             scalarAllocations.add(new Object[] { 42, factory,
261                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
262                     (AllocationFunction.OfInt) SegmentAllocator::allocateFrom,
263                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
264             scalarAllocations.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN),
265                     (AllocationFunction.OfFloat) SegmentAllocator::allocateFrom,
266                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
267             scalarAllocations.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN),
268                     (AllocationFunction.OfLong) SegmentAllocator::allocateFrom,
269                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
270             scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN),
271                     (AllocationFunction.OfDouble) SegmentAllocator::allocateFrom,
272                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
273             scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
274                     (AllocationFunction.OfAddress) SegmentAllocator::allocateFrom,
275                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
276 
277             scalarAllocations.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN),
278                     (AllocationFunction.OfShort) SegmentAllocator::allocateFrom,
279                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
280             scalarAllocations.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN),
281                     (AllocationFunction.OfChar) SegmentAllocator::allocateFrom,
282                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
283             scalarAllocations.add(new Object[] { 42, factory,
284                     ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN),
285                     (AllocationFunction.OfInt) SegmentAllocator::allocateFrom,
286                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
287             scalarAllocations.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN),
288                     (AllocationFunction.OfFloat) SegmentAllocator::allocateFrom,
289                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
290             scalarAllocations.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN),
291                     (AllocationFunction.OfLong) SegmentAllocator::allocateFrom,
292                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
293             scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN),
294                     (AllocationFunction.OfDouble) SegmentAllocator::allocateFrom,
295                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
296             scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
297                     (AllocationFunction.OfAddress) SegmentAllocator::allocateFrom,
298                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
299         }
300         return scalarAllocations.toArray(Object[][]::new);
301     }
302 
303     @DataProvider(name = "arrayAllocations")
304     static Object[][] arrayAllocations() {
305         List<Object[]> arrayAllocations = new ArrayList<>();
306         for (AllocationFactory factory : AllocationFactory.values()) {
307             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_BYTE,
308                     (AllocationFunction.OfByteArray) SegmentAllocator::allocateFrom,
309                     ToArrayHelper.toByteArray });
310             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN),
311                     (AllocationFunction.OfCharArray) SegmentAllocator::allocateFrom,
312                     ToArrayHelper.toCharArray });
313             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN),
314                     (AllocationFunction.OfShortArray) SegmentAllocator::allocateFrom,
315                     ToArrayHelper.toShortArray });
316             arrayAllocations.add(new Object[] { factory,
317                     ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN),
318                     (AllocationFunction.OfIntArray) SegmentAllocator::allocateFrom,
319                     ToArrayHelper.toIntArray });
320             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN),
321                     (AllocationFunction.OfFloatArray) SegmentAllocator::allocateFrom,
322                     ToArrayHelper.toFloatArray });
323             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN),
324                     (AllocationFunction.OfLongArray) SegmentAllocator::allocateFrom,
325                     ToArrayHelper.toLongArray });
326             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN),
327                     (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateFrom,
328                     ToArrayHelper.toDoubleArray });
329 
330             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN),
331                     (AllocationFunction.OfCharArray) SegmentAllocator::allocateFrom,
332                     ToArrayHelper.toCharArray });
333             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN),
334                     (AllocationFunction.OfShortArray) SegmentAllocator::allocateFrom,
335                     ToArrayHelper.toShortArray });
336             arrayAllocations.add(new Object[] { factory,
337                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
338                     (AllocationFunction.OfIntArray) SegmentAllocator::allocateFrom,
339                     ToArrayHelper.toIntArray });
340             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN),
341                     (AllocationFunction.OfFloatArray) SegmentAllocator::allocateFrom,
342                     ToArrayHelper.toFloatArray });
343             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN),
344                     (AllocationFunction.OfLongArray) SegmentAllocator::allocateFrom,
345                     ToArrayHelper.toLongArray });
346             arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN),
347                     (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateFrom,
348                     ToArrayHelper.toDoubleArray });
349         };
350         return arrayAllocations.toArray(Object[][]::new);
351     }
352 
353     interface AllocationFunction<X, L extends ValueLayout> {
354         MemorySegment allocate(SegmentAllocator allocator, L layout, X value);
355 
356         interface OfByte extends AllocationFunction<Byte, ValueLayout.OfByte> { }
357         interface OfBoolean extends AllocationFunction<Boolean, ValueLayout.OfBoolean> { }
358         interface OfChar extends AllocationFunction<Character, ValueLayout.OfChar> { }
359         interface OfShort extends AllocationFunction<Short, ValueLayout.OfShort> { }
360         interface OfInt extends AllocationFunction<Integer, ValueLayout.OfInt> { }
361         interface OfFloat extends AllocationFunction<Float, ValueLayout.OfFloat> { }
362         interface OfLong extends AllocationFunction<Long, ValueLayout.OfLong> { }
363         interface OfDouble extends AllocationFunction<Double, ValueLayout.OfDouble> { }
364         interface OfAddress extends AllocationFunction<MemorySegment, AddressLayout> { }
365 
366         interface OfByteArray extends AllocationFunction<byte[], ValueLayout.OfByte> { }
367         interface OfCharArray extends AllocationFunction<char[], ValueLayout.OfChar> { }
368         interface OfShortArray extends AllocationFunction<short[], ValueLayout.OfShort> { }
369         interface OfIntArray extends AllocationFunction<int[], ValueLayout.OfInt> { }
370         interface OfFloatArray extends AllocationFunction<float[], ValueLayout.OfFloat> { }
371         interface OfLongArray extends AllocationFunction<long[], ValueLayout.OfLong> { }
372         interface OfDoubleArray extends AllocationFunction<double[], ValueLayout.OfDouble> { }
373     }
374 
375     enum AllocationFactory {
376         SLICING(true, (size, arena) -> {
377             return SegmentAllocator.slicingAllocator(arena.allocate(size, 1));
378         });
379 
380         private final boolean isBound;
381         private final BiFunction<Long, Arena, SegmentAllocator> factory;
382 
383         AllocationFactory(boolean isBound, BiFunction<Long, Arena, SegmentAllocator> factory) {
384             this.isBound = isBound;
385             this.factory = factory;
386         }
387 
388         SegmentAllocator allocator(long size, Arena arena) {
389             return factory.apply(size, arena);
390         }
391 
392         public boolean isBound() {
393             return isBound;
394         }
395     }
396 
397     interface ToArrayHelper<T> {
398         T array();
399         T toArray(MemorySegment segment, ValueLayout layout);
400 
401         ToArrayHelper<byte[]> toByteArray = new ToArrayHelper<>() {
402             @Override
403             public byte[] array() {
404                 return new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
405             }
406 
407             @Override
408             public byte[] toArray(MemorySegment segment, ValueLayout layout) {
409                 ByteBuffer buffer = segment.asByteBuffer().order(layout.order());
410                 byte[] found = new byte[buffer.limit()];
411                 buffer.get(found);
412                 return found;
413             }
414         };
415 
416         ToArrayHelper<char[]> toCharArray = new ToArrayHelper<>() {
417             @Override
418             public char[] array() {
419                 return new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
420             }
421 
422             @Override
423             public char[] toArray(MemorySegment segment, ValueLayout layout) {
424                 CharBuffer buffer = segment.asByteBuffer().order(layout.order()).asCharBuffer();
425                 char[] found = new char[buffer.limit()];
426                 buffer.get(found);
427                 return found;
428             }
429         };
430 
431         ToArrayHelper<short[]> toShortArray = new ToArrayHelper<>() {
432             @Override
433             public short[] array() {
434                 return new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
435             }
436 
437             @Override
438             public short[] toArray(MemorySegment segment, ValueLayout layout) {
439                 ShortBuffer buffer = segment.asByteBuffer().order(layout.order()).asShortBuffer();
440                 short[] found = new short[buffer.limit()];
441                 buffer.get(found);
442                 return found;
443             }
444         };
445 
446         ToArrayHelper<int[]> toIntArray = new ToArrayHelper<>() {
447             @Override
448             public int[] array() {
449                 return new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
450             }
451 
452             @Override
453             public int[] toArray(MemorySegment segment, ValueLayout layout) {
454                 IntBuffer buffer = segment.asByteBuffer().order(layout.order()).asIntBuffer();
455                 int[] found = new int[buffer.limit()];
456                 buffer.get(found);
457                 return found;
458             }
459         };
460 
461         ToArrayHelper<float[]> toFloatArray = new ToArrayHelper<>() {
462             @Override
463             public float[] array() {
464                 return new float[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
465             }
466 
467             @Override
468             public float[] toArray(MemorySegment segment, ValueLayout layout) {
469                 FloatBuffer buffer = segment.asByteBuffer().order(layout.order()).asFloatBuffer();
470                 float[] found = new float[buffer.limit()];
471                 buffer.get(found);
472                 return found;
473             }
474         };
475 
476         ToArrayHelper<long[]> toLongArray = new ToArrayHelper<>() {
477             @Override
478             public long[] array() {
479                 return new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
480             }
481 
482             @Override
483             public long[] toArray(MemorySegment segment, ValueLayout layout) {
484                 LongBuffer buffer = segment.asByteBuffer().order(layout.order()).asLongBuffer();
485                 long[] found = new long[buffer.limit()];
486                 buffer.get(found);
487                 return found;
488             }
489         };
490 
491         ToArrayHelper<double[]> toDoubleArray = new ToArrayHelper<>() {
492             @Override
493             public double[] array() {
494                 return new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
495             }
496 
497             @Override
498             public double[] toArray(MemorySegment segment, ValueLayout layout) {
499                 DoubleBuffer buffer = segment.asByteBuffer().order(layout.order()).asDoubleBuffer();
500                 double[] found = new double[buffer.limit()];
501                 buffer.get(found);
502                 return found;
503             }
504         };
505     }
506 
507     @DataProvider(name = "allocators")
508     static Object[][] allocators() {
509         return new Object[][] {
510                 { SegmentAllocator.prefixAllocator(Arena.global().allocate(10, 1)) },
511         };
512     }
513 }