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