< prev index next >

test/jdk/java/foreign/TestSegmentAllocators.java

Print this page

 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  * @run testng/othervm TestSegmentAllocators
 28  */
 29 
 30 import jdk.incubator.foreign.*;
 31 
 32 import org.testng.annotations.*;
 33 
 34 import java.lang.invoke.VarHandle;
 35 import java.nio.ByteBuffer;
 36 import java.nio.ByteOrder;

 37 import java.nio.DoubleBuffer;
 38 import java.nio.FloatBuffer;
 39 import java.nio.IntBuffer;
 40 import java.nio.LongBuffer;
 41 import java.nio.ShortBuffer;
 42 import java.util.ArrayList;
 43 import java.util.List;
 44 import java.util.function.BiFunction;
 45 import java.util.function.Function;
 46 import java.util.stream.IntStream;
 47 import java.util.stream.LongStream;
 48 
 49 import static org.testng.Assert.*;
 50 
 51 public class TestSegmentAllocators {
 52 
 53     final static int ELEMS = 128;
 54     final static Class<?> ADDRESS_CARRIER = MemoryLayouts.ADDRESS.bitSize() == 64 ? long.class : int.class;
 55 
 56     @Test(dataProvider = "nativeScopes")
 57     public <Z> void testAllocation(Z value, AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Z> allocationFunction, Function<MemoryLayout, VarHandle> handleFactory) {
 58         ValueLayout[] layouts = {


 59                 layout,
 60                 layout.withBitAlignment(layout.bitAlignment() * 2),
 61                 layout.withBitAlignment(layout.bitAlignment() * 4),
 62                 layout.withBitAlignment(layout.bitAlignment() * 8)
 63         };
 64         for (ValueLayout alignedLayout : layouts) {
 65             List<MemorySegment> addressList = new ArrayList<>();
 66             int elems = ELEMS / ((int)alignedLayout.byteAlignment() / (int)layout.byteAlignment());
 67             ResourceScope[] scopes = {
 68                     ResourceScope.newConfinedScope(),
 69                     ResourceScope.newSharedScope()
 70             };
 71             for (ResourceScope scope : scopes) {
 72                 try (scope) {
 73                     SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, scope);
 74                     for (int i = 0; i < elems; i++) {
 75                         MemorySegment address = allocationFunction.allocate(allocator, alignedLayout, value);
 76                         assertEquals(address.byteSize(), alignedLayout.byteSize());
 77                         addressList.add(address);
 78                         VarHandle handle = handleFactory.apply(alignedLayout);
 79                         assertEquals(value, handle.get(address));
 80                     }
 81                     boolean isBound = allocationFactory.isBound();
 82                     try {
 83                         allocationFunction.allocate(allocator, alignedLayout, value); //too much, should fail if bound
 84                         assertFalse(isBound);
 85                     } catch (OutOfMemoryError ex) {
 86                         //failure is expected if bound
 87                         assertTrue(isBound);
 88                     }
 89                 }
 90                 // addresses should be invalid now
 91                 for (MemorySegment address : addressList) {
 92                     assertFalse(address.scope().isAlive());


 93                 }
 94             }
 95         }
 96     }
 97 
 98     static final int SIZE_256M = 1024 * 1024 * 256;
 99 
100     @Test
101     public void testBigAllocationInUnboundedScope() {
102         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
103             SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope);
104             for (int i = 8 ; i < SIZE_256M ; i *= 8) {
105                 MemorySegment address = allocator.allocate(i, i);
106                 //check size
107                 assertEquals(address.byteSize(), i);
108                 //check alignment
109                 assertEquals(address.address().toRawLongValue() % i, 0);
110             }
111         }
112     }
113 
114     @Test(expectedExceptions = OutOfMemoryError.class)
115     public void testTooBigForBoundedArena() {
116         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
117             SegmentAllocator allocator = SegmentAllocator.arenaAllocator(10, scope);
118             allocator.allocate(12);
119         }
120     }
121 
122     @Test
123     public void testBiggerThanBlockForBoundedArena() {
124         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
125             SegmentAllocator allocator = SegmentAllocator.arenaAllocator(4 * 1024 * 2, scope);
126             allocator.allocate(4 * 1024 + 1); // should be ok
127         }
128     }
129 





130     @Test(dataProvider = "arrayScopes")
131     public <Z> void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Object> allocationFunction, ToArrayHelper<Z> arrayHelper) {
132         Z arr = arrayHelper.array();
133         ResourceScope[] scopes = {
134                 ResourceScope.newConfinedScope(),
135                 ResourceScope.newSharedScope()
136         };
137         for (ResourceScope scope : scopes) {
138             try (scope) {
139                 SegmentAllocator allocator = allocationFactory.allocator(100, scope);
140                 MemorySegment address = allocationFunction.allocate(allocator, layout, arr);
141                 Z found = arrayHelper.toArray(address, layout);
142                 assertEquals(found, arr);
143             }
144         }
145     }
146 
147     @DataProvider(name = "nativeScopes")
148     static Object[][] nativeScopes() {
149         return new Object[][] {
150                 { (byte)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_8_BE,
151                         (AllocationFunction<Byte>) SegmentAllocator::allocate,
152                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(byte.class) },
153                 { (short)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_BE,
154                         (AllocationFunction<Short>) SegmentAllocator::allocate,
155                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(short.class) },
156                 { (char)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_BE,
157                         (AllocationFunction<Character>) SegmentAllocator::allocate,
158                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(char.class) },
159                 { 42, AllocationFactory.BOUNDED,
160                         MemoryLayouts.BITS_32_BE,
161                         (AllocationFunction<Integer>) SegmentAllocator::allocate,
162                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(int.class) },
163                 { 42f, AllocationFactory.BOUNDED, MemoryLayouts.BITS_32_BE,
164                         (AllocationFunction<Float>) SegmentAllocator::allocate,
165                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(float.class) },
166                 { 42L, AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_BE,
167                         (AllocationFunction<Long>) SegmentAllocator::allocate,
168                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(long.class) },
169                 { 42d, AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_BE,
170                         (AllocationFunction<Double>) SegmentAllocator::allocate,
171                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(double.class) },
172                 { MemoryAddress.ofLong(42), AllocationFactory.BOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
173                         (AllocationFunction<MemoryAddress>) SegmentAllocator::allocate,
174                         (Function<MemoryLayout, VarHandle>)l -> MemoryHandles.asAddressVarHandle(l.varHandle(ADDRESS_CARRIER)) },
175 
176                 { (byte)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_8_LE,
177                         (AllocationFunction<Byte>) SegmentAllocator::allocate,
178                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(byte.class) },
179                 { (short)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_LE,
180                         (AllocationFunction<Short>) SegmentAllocator::allocate,
181                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(short.class) },
182                 { (char)42, AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_LE,
183                         (AllocationFunction<Character>) SegmentAllocator::allocate,
184                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(char.class) },
185                 { 42, AllocationFactory.BOUNDED,
186                         MemoryLayouts.BITS_32_LE,
187                         (AllocationFunction<Integer>) SegmentAllocator::allocate,
188                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(int.class) },
189                 { 42f, AllocationFactory.BOUNDED, MemoryLayouts.BITS_32_LE,
190                         (AllocationFunction<Float>) SegmentAllocator::allocate,
191                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(float.class) },
192                 { 42L, AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_LE,
193                         (AllocationFunction<Long>) SegmentAllocator::allocate,
194                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(long.class) },
195                 { 42d, AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_LE,
196                         (AllocationFunction<Double>) SegmentAllocator::allocate,
197                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(double.class) },
198                 { MemoryAddress.ofLong(42), AllocationFactory.BOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN),
199                         (AllocationFunction<MemoryAddress>) SegmentAllocator::allocate,
200                         (Function<MemoryLayout, VarHandle>)l -> MemoryHandles.asAddressVarHandle(l.varHandle(ADDRESS_CARRIER)) },
201 
202                 { (byte)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_8_BE,
203                         (AllocationFunction<Byte>) SegmentAllocator::allocate,
204                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(byte.class) },
205                 { (short)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_BE,
206                         (AllocationFunction<Short>) SegmentAllocator::allocate,
207                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(short.class) },
208                 { (char)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_BE,
209                         (AllocationFunction<Character>) SegmentAllocator::allocate,
210                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(char.class) },
211                 { 42, AllocationFactory.UNBOUNDED,
212                         MemoryLayouts.BITS_32_BE,
213                         (AllocationFunction<Integer>) SegmentAllocator::allocate,
214                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(int.class) },
215                 { 42f, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_32_BE,
216                         (AllocationFunction<Float>) SegmentAllocator::allocate,
217                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(float.class) },
218                 { 42L, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_BE,
219                         (AllocationFunction<Long>) SegmentAllocator::allocate,
220                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(long.class) },
221                 { 42d, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_BE,
222                         (AllocationFunction<Double>) SegmentAllocator::allocate,
223                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(double.class) },
224                 { MemoryAddress.ofLong(42), AllocationFactory.UNBOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
225                         (AllocationFunction<MemoryAddress>) SegmentAllocator::allocate,
226                         (Function<MemoryLayout, VarHandle>)l -> MemoryHandles.asAddressVarHandle(l.varHandle(ADDRESS_CARRIER)) },
227 
228                 { (byte)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_8_LE,
229                         (AllocationFunction<Byte>) SegmentAllocator::allocate,
230                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(byte.class) },
231                 { (short)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_LE,
232                         (AllocationFunction<Short>) SegmentAllocator::allocate,
233                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(short.class) },
234                 { (char)42, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_LE,
235                         (AllocationFunction<Character>) SegmentAllocator::allocate,
236                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(char.class) },
237                 { 42, AllocationFactory.UNBOUNDED,
238                         MemoryLayouts.BITS_32_LE,
239                         (AllocationFunction<Integer>) SegmentAllocator::allocate,
240                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(int.class) },
241                 { 42f, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_32_LE,
242                         (AllocationFunction<Float>) SegmentAllocator::allocate,
243                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(float.class) },
244                 { 42L, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_LE,
245                         (AllocationFunction<Long>) SegmentAllocator::allocate,
246                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(long.class) },
247                 { 42d, AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_LE,
248                         (AllocationFunction<Double>) SegmentAllocator::allocate,
249                         (Function<MemoryLayout, VarHandle>)l -> l.varHandle(double.class) },
250                 { MemoryAddress.ofLong(42), AllocationFactory.UNBOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN),
251                         (AllocationFunction<MemoryAddress>) SegmentAllocator::allocate,
252                         (Function<MemoryLayout, VarHandle>)l -> MemoryHandles.asAddressVarHandle(l.varHandle(ADDRESS_CARRIER)) },
253         };
254     }
255 
256     @DataProvider(name = "arrayScopes")
257     static Object[][] arrayScopes() {
258         return new Object[][] {
259                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_8_LE,
260                         (AllocationFunction<byte[]>) SegmentAllocator::allocateArray,
261                         ToArrayHelper.toByteArray },
262                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_LE,
263                         (AllocationFunction<short[]>) SegmentAllocator::allocateArray,
264                         ToArrayHelper.toShortArray },
265                 { AllocationFactory.BOUNDED,
266                         MemoryLayouts.BITS_32_LE,
267                         (AllocationFunction<int[]>) SegmentAllocator::allocateArray,
268                         ToArrayHelper.toIntArray },
269                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_32_LE,
270                         (AllocationFunction<float[]>) SegmentAllocator::allocateArray,
271                         ToArrayHelper.toFloatArray },
272                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_LE,
273                         (AllocationFunction<long[]>) SegmentAllocator::allocateArray,
274                         ToArrayHelper.toLongArray },
275                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_LE,
276                         (AllocationFunction<double[]>) SegmentAllocator::allocateArray,
277                         ToArrayHelper.toDoubleArray },
278                 { AllocationFactory.BOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN),
279                         (AllocationFunction<MemoryAddress[]>) SegmentAllocator::allocateArray,
280                         ToArrayHelper.toAddressArray },
281 
282 
283                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_8_BE,
284                         (AllocationFunction<byte[]>) SegmentAllocator::allocateArray,
285                         ToArrayHelper.toByteArray },
286                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_16_BE,
287                         (AllocationFunction<short[]>) SegmentAllocator::allocateArray,
288                         ToArrayHelper.toShortArray },
289                 { AllocationFactory.BOUNDED,
290                         MemoryLayouts.BITS_32_BE,
291                         (AllocationFunction<int[]>) SegmentAllocator::allocateArray,
292                         ToArrayHelper.toIntArray },
293                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_32_BE,
294                         (AllocationFunction<float[]>) SegmentAllocator::allocateArray,
295                         ToArrayHelper.toFloatArray },
296                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_BE,
297                         (AllocationFunction<long[]>) SegmentAllocator::allocateArray,
298                         ToArrayHelper.toLongArray },
299                 { AllocationFactory.BOUNDED, MemoryLayouts.BITS_64_BE,
300                         (AllocationFunction<double[]>) SegmentAllocator::allocateArray,
301                         ToArrayHelper.toDoubleArray },
302                 { AllocationFactory.BOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
303                         (AllocationFunction<MemoryAddress[]>) SegmentAllocator::allocateArray,
304                         ToArrayHelper.toAddressArray },
305 
306                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_8_LE,
307                         (AllocationFunction<byte[]>) SegmentAllocator::allocateArray,
308                         ToArrayHelper.toByteArray },
309                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_LE,
310                         (AllocationFunction<short[]>) SegmentAllocator::allocateArray,
311                         ToArrayHelper.toShortArray },
312                 { AllocationFactory.UNBOUNDED,
313                         MemoryLayouts.BITS_32_LE,
314                         (AllocationFunction<int[]>) SegmentAllocator::allocateArray,
315                         ToArrayHelper.toIntArray },
316                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_32_LE,
317                         (AllocationFunction<float[]>) SegmentAllocator::allocateArray,
318                         ToArrayHelper.toFloatArray },
319                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_LE,
320                         (AllocationFunction<long[]>) SegmentAllocator::allocateArray,
321                         ToArrayHelper.toLongArray },
322                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_LE,
323                         (AllocationFunction<double[]>) SegmentAllocator::allocateArray,
324                         ToArrayHelper.toDoubleArray },
325                 { AllocationFactory.UNBOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.LITTLE_ENDIAN),
326                         (AllocationFunction<MemoryAddress[]>) SegmentAllocator::allocateArray,
327                         ToArrayHelper.toAddressArray },
328 
329 
330                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_8_BE,
331                         (AllocationFunction<byte[]>) SegmentAllocator::allocateArray,
332                         ToArrayHelper.toByteArray },
333                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_16_BE,
334                         (AllocationFunction<short[]>) SegmentAllocator::allocateArray,
335                         ToArrayHelper.toShortArray },
336                 { AllocationFactory.UNBOUNDED,
337                         MemoryLayouts.BITS_32_BE,
338                         (AllocationFunction<int[]>) SegmentAllocator::allocateArray,
339                         ToArrayHelper.toIntArray },
340                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_32_BE,
341                         (AllocationFunction<float[]>) SegmentAllocator::allocateArray,
342                         ToArrayHelper.toFloatArray },
343                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_BE,
344                         (AllocationFunction<long[]>) SegmentAllocator::allocateArray,
345                         ToArrayHelper.toLongArray },
346                 { AllocationFactory.UNBOUNDED, MemoryLayouts.BITS_64_BE,
347                         (AllocationFunction<double[]>) SegmentAllocator::allocateArray,
348                         ToArrayHelper.toDoubleArray },
349                 { AllocationFactory.UNBOUNDED, MemoryLayouts.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
350                         (AllocationFunction<MemoryAddress[]>) SegmentAllocator::allocateArray,
351                         ToArrayHelper.toAddressArray },
352         };

353     }
354 
355     interface AllocationFunction<X> {
356         MemorySegment allocate(SegmentAllocator allocator, ValueLayout layout, X value);


















357     }
358 
359     static class AllocationFactory {





360         private final boolean isBound;
361         private final BiFunction<Long, ResourceScope, SegmentAllocator> factory;
362 
363         private AllocationFactory(boolean isBound, BiFunction<Long, ResourceScope, SegmentAllocator> factory) {
364             this.isBound = isBound;
365             this.factory = factory;
366         }
367 
368         SegmentAllocator allocator(long size, ResourceScope scope) {
369             return factory.apply(size, scope);
370         }
371 
372         public boolean isBound() {
373             return isBound;
374         }
375 
376         static AllocationFactory BOUNDED = new AllocationFactory(true, SegmentAllocator::arenaAllocator);
377         static AllocationFactory UNBOUNDED = new AllocationFactory(false, (size, scope) -> SegmentAllocator.arenaAllocator(scope));
378     }
379 
380     interface ToArrayHelper<T> {
381         T array();
382         T toArray(MemorySegment segment, ValueLayout layout);
383 
384         ToArrayHelper<byte[]> toByteArray = new ToArrayHelper<>() {
385             @Override
386             public byte[] array() {
387                 return new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
388             }
389 
390             @Override
391             public byte[] toArray(MemorySegment segment, ValueLayout layout) {
392                 ByteBuffer buffer = segment.asByteBuffer().order(layout.order());
393                 byte[] found = new byte[buffer.limit()];
394                 buffer.get(found);
395                 return found;
396             }
397         };
398 















399         ToArrayHelper<short[]> toShortArray = new ToArrayHelper<>() {
400             @Override
401             public short[] array() {
402                 return new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
403             }
404 
405             @Override
406             public short[] toArray(MemorySegment segment, ValueLayout layout) {
407                 ShortBuffer buffer = segment.asByteBuffer().order(layout.order()).asShortBuffer();
408                 short[] found = new short[buffer.limit()];
409                 buffer.get(found);
410                 return found;
411             }
412         };
413 
414         ToArrayHelper<int[]> toIntArray = new ToArrayHelper<>() {
415             @Override
416             public int[] array() {
417                 return new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
418             }

457         };
458 
459         ToArrayHelper<double[]> toDoubleArray = new ToArrayHelper<>() {
460             @Override
461             public double[] array() {
462                 return new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
463             }
464 
465             @Override
466             public double[] toArray(MemorySegment segment, ValueLayout layout) {
467                 DoubleBuffer buffer = segment.asByteBuffer().order(layout.order()).asDoubleBuffer();
468                 double[] found = new double[buffer.limit()];
469                 buffer.get(found);
470                 return found;
471             }
472         };
473 
474         ToArrayHelper<MemoryAddress[]> toAddressArray = new ToArrayHelper<>() {
475             @Override
476             public MemoryAddress[] array() {
477                 return switch ((int)MemoryLayouts.ADDRESS.byteSize()) {
478                     case 4 -> wrap(toIntArray.array());
479                     case 8 -> wrap(toLongArray.array());
480                     default -> throw new IllegalStateException("Cannot get here");
481                 };
482             }
483 
484             @Override
485             public MemoryAddress[] toArray(MemorySegment segment, ValueLayout layout) {
486                 return switch ((int)layout.byteSize()) {
487                     case 4 -> wrap(toIntArray.toArray(segment, layout));
488                     case 8 -> wrap(toLongArray.toArray(segment, layout));
489                     default -> throw new IllegalStateException("Cannot get here");
490                 };
491             }
492 
493             private MemoryAddress[] wrap(int[] ints) {
494                 return IntStream.of(ints).mapToObj(MemoryAddress::ofLong).toArray(MemoryAddress[]::new);
495             }
496 
497             private MemoryAddress[] wrap(long[] ints) {

 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  * @run testng/othervm TestSegmentAllocators
 28  */
 29 
 30 import jdk.incubator.foreign.*;
 31 
 32 import org.testng.annotations.*;
 33 
 34 import java.lang.invoke.VarHandle;
 35 import java.nio.ByteBuffer;
 36 import java.nio.ByteOrder;
 37 import java.nio.CharBuffer;
 38 import java.nio.DoubleBuffer;
 39 import java.nio.FloatBuffer;
 40 import java.nio.IntBuffer;
 41 import java.nio.LongBuffer;
 42 import java.nio.ShortBuffer;
 43 import java.util.ArrayList;
 44 import java.util.List;
 45 import java.util.function.BiFunction;
 46 import java.util.function.Function;
 47 import java.util.stream.IntStream;
 48 import java.util.stream.LongStream;
 49 
 50 import static org.testng.Assert.*;
 51 
 52 public class TestSegmentAllocators {
 53 
 54     final static int ELEMS = 128;
 55     final static Class<?> ADDRESS_CARRIER = ValueLayout.ADDRESS.bitSize() == 64 ? long.class : int.class;
 56 
 57     @Test(dataProvider = "nativeScopes")
 58     @SuppressWarnings("unchecked")
 59     public <Z, L extends ValueLayout> void testAllocation(Z value, AllocationFactory allocationFactory, L layout, AllocationFunction<Z, L> allocationFunction, Function<MemoryLayout, VarHandle> handleFactory) {
 60         layout = (L)layout.withBitAlignment(layout.bitSize());
 61         L[] layouts = (L[])new ValueLayout[] {
 62                 layout,
 63                 layout.withBitAlignment(layout.bitAlignment() * 2),
 64                 layout.withBitAlignment(layout.bitAlignment() * 4),
 65                 layout.withBitAlignment(layout.bitAlignment() * 8)
 66         };
 67         for (L alignedLayout : layouts) {
 68             List<MemorySegment> addressList = new ArrayList<>();
 69             int elems = ELEMS / ((int)alignedLayout.byteAlignment() / (int)layout.byteAlignment());
 70             ResourceScope[] scopes = {
 71                     ResourceScope.newConfinedScope(),
 72                     ResourceScope.newSharedScope()
 73             };
 74             for (ResourceScope scope : scopes) {
 75                 try (scope) {
 76                     SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, scope);
 77                     for (int i = 0; i < elems; i++) {
 78                         MemorySegment address = allocationFunction.allocate(allocator, alignedLayout, value);
 79                         assertEquals(address.byteSize(), alignedLayout.byteSize());
 80                         addressList.add(address);
 81                         VarHandle handle = handleFactory.apply(alignedLayout);
 82                         assertEquals(value, handle.get(address));
 83                     }
 84                     boolean isBound = allocationFactory.isBound();
 85                     try {
 86                         allocationFunction.allocate(allocator, alignedLayout, value);
 87                         assertFalse(isBound);
 88                     } catch (OutOfMemoryError ex) {
 89                         //failure is expected if bound
 90                         assertTrue(isBound);
 91                     }
 92                 }
 93                 if (allocationFactory != AllocationFactory.IMPLICIT_ALLOCATOR) {
 94                     // addresses should be invalid now
 95                     for (MemorySegment address : addressList) {
 96                         assertFalse(address.scope().isAlive());
 97                     }
 98                 }
 99             }
100         }
101     }
102 
103     static final int SIZE_256M = 1024 * 1024 * 256;
104 
105     @Test
106     public void testBigAllocationInUnboundedScope() {
107         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
108             SegmentAllocator allocator = SegmentAllocator.newNativeArena(scope);
109             for (int i = 8 ; i < SIZE_256M ; i *= 8) {
110                 MemorySegment address = allocator.allocate(i, i);
111                 //check size
112                 assertEquals(address.byteSize(), i);
113                 //check alignment
114                 assertEquals(address.address().toRawLongValue() % i, 0);
115             }
116         }
117     }
118 
119     @Test(expectedExceptions = OutOfMemoryError.class)
120     public void testTooBigForBoundedArena() {
121         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
122             SegmentAllocator allocator = SegmentAllocator.newNativeArena(10, scope);
123             allocator.allocate(12);
124         }
125     }
126 
127     @Test
128     public void testBiggerThanBlockForBoundedArena() {
129         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
130             SegmentAllocator allocator = SegmentAllocator.newNativeArena(4 * 1024 * 2, scope);
131             allocator.allocate(4 * 1024 + 1); // should be ok
132         }
133     }
134 
135     @Test(expectedExceptions = IllegalArgumentException.class)
136     public void testBadUnboundedArenaSize() {
137         SegmentAllocator.newNativeArena( -1, ResourceScope.globalScope());
138     }
139 
140     @Test(dataProvider = "arrayScopes")
141     public <Z> void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Object, ValueLayout> allocationFunction, ToArrayHelper<Z> arrayHelper) {
142         Z arr = arrayHelper.array();
143         ResourceScope[] scopes = {
144                 ResourceScope.newConfinedScope(),
145                 ResourceScope.newSharedScope()
146         };
147         for (ResourceScope scope : scopes) {
148             try (scope) {
149                 SegmentAllocator allocator = allocationFactory.allocator(100, scope);
150                 MemorySegment address = allocationFunction.allocate(allocator, layout, arr);
151                 Z found = arrayHelper.toArray(address, layout);
152                 assertEquals(found, arr);
153             }
154         }
155     }
156 
157     @DataProvider(name = "nativeScopes")
158     static Object[][] nativeScopes() {
159         List<Object[]> nativeScopes = new ArrayList<>();
160         for (AllocationFactory factory : AllocationFactory.values()) {
161             nativeScopes.add(new Object[] { (byte)42, factory, ValueLayout.JAVA_BYTE,
162                     (AllocationFunction.OfByte) SegmentAllocator::allocate,
163                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
164             nativeScopes.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN),
165                     (AllocationFunction.OfShort) SegmentAllocator::allocate,
166                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
167             nativeScopes.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN),
168                     (AllocationFunction.OfChar) SegmentAllocator::allocate,
169                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
170             nativeScopes.add(new Object[] { 42, factory,
171                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
172                     (AllocationFunction.OfInt) SegmentAllocator::allocate,
173                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
174             nativeScopes.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN),
175                     (AllocationFunction.OfFloat) SegmentAllocator::allocate,
176                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
177             nativeScopes.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN),
178                     (AllocationFunction.OfLong) SegmentAllocator::allocate,
179                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
180             nativeScopes.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN),
181                     (AllocationFunction.OfDouble) SegmentAllocator::allocate,
182                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
183             nativeScopes.add(new Object[] { MemoryAddress.ofLong(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
184                     (AllocationFunction.OfAddress) SegmentAllocator::allocate,
185                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
186 
187             nativeScopes.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN),
188                     (AllocationFunction.OfShort) SegmentAllocator::allocate,
189                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
190             nativeScopes.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN),
191                     (AllocationFunction.OfChar) SegmentAllocator::allocate,
192                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
193             nativeScopes.add(new Object[] { 42, factory,
194                     ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN),
195                     (AllocationFunction.OfInt) SegmentAllocator::allocate,
196                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
197             nativeScopes.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN),
198                     (AllocationFunction.OfFloat) SegmentAllocator::allocate,
199                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
200             nativeScopes.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN),
201                     (AllocationFunction.OfLong) SegmentAllocator::allocate,
202                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
203             nativeScopes.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN),
204                     (AllocationFunction.OfDouble) SegmentAllocator::allocate,
205                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
206             nativeScopes.add(new Object[] { MemoryAddress.ofLong(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
207                     (AllocationFunction.OfAddress) SegmentAllocator::allocate,
208                     (Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
209         }
210         return nativeScopes.toArray(Object[][]::new);





















































211     }
212 
213     @DataProvider(name = "arrayScopes")
214     static Object[][] arrayScopes() {
215         List<Object[]> arrayScopes = new ArrayList<>();
216         for (AllocationFactory factory : AllocationFactory.values()) {
217             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_BYTE,
218                     (AllocationFunction.OfByteArray) SegmentAllocator::allocateArray,
219                     ToArrayHelper.toByteArray });
220             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN),
221                     (AllocationFunction.OfCharArray) SegmentAllocator::allocateArray,
222                     ToArrayHelper.toCharArray });
223             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN),
224                     (AllocationFunction.OfShortArray) SegmentAllocator::allocateArray,
225                     ToArrayHelper.toShortArray });
226             arrayScopes.add(new Object[] { factory,
227                     ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN),
228                     (AllocationFunction.OfIntArray) SegmentAllocator::allocateArray,
229                     ToArrayHelper.toIntArray });
230             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN),
231                     (AllocationFunction.OfFloatArray) SegmentAllocator::allocateArray,
232                     ToArrayHelper.toFloatArray });
233             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN),
234                     (AllocationFunction.OfLongArray) SegmentAllocator::allocateArray,
235                     ToArrayHelper.toLongArray });
236             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN),
237                     (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateArray,
238                     ToArrayHelper.toDoubleArray });
239 
240             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN),
241                     (AllocationFunction.OfCharArray) SegmentAllocator::allocateArray,
242                     ToArrayHelper.toCharArray });
243             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN),
244                     (AllocationFunction.OfShortArray) SegmentAllocator::allocateArray,
245                     ToArrayHelper.toShortArray });
246             arrayScopes.add(new Object[] { factory,
247                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
248                     (AllocationFunction.OfIntArray) SegmentAllocator::allocateArray,
249                     ToArrayHelper.toIntArray });
250             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN),
251                     (AllocationFunction.OfFloatArray) SegmentAllocator::allocateArray,
252                     ToArrayHelper.toFloatArray });
253             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN),
254                     (AllocationFunction.OfLongArray) SegmentAllocator::allocateArray,
255                     ToArrayHelper.toLongArray });
256             arrayScopes.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN),
257                     (AllocationFunction.OfDoubleArray) SegmentAllocator::allocateArray,
258                     ToArrayHelper.toDoubleArray });


















































259         };
260         return arrayScopes.toArray(Object[][]::new);
261     }
262 
263     interface AllocationFunction<X, L extends ValueLayout> {
264         MemorySegment allocate(SegmentAllocator allocator, L layout, X value);
265 
266         interface OfByte extends AllocationFunction<Byte, ValueLayout.OfByte> { }
267         interface OfBoolean extends AllocationFunction<Boolean, ValueLayout.OfBoolean> { }
268         interface OfChar extends AllocationFunction<Character, ValueLayout.OfChar> { }
269         interface OfShort extends AllocationFunction<Short, ValueLayout.OfShort> { }
270         interface OfInt extends AllocationFunction<Integer, ValueLayout.OfInt> { }
271         interface OfFloat extends AllocationFunction<Float, ValueLayout.OfFloat> { }
272         interface OfLong extends AllocationFunction<Long, ValueLayout.OfLong> { }
273         interface OfDouble extends AllocationFunction<Double, ValueLayout.OfDouble> { }
274         interface OfAddress extends AllocationFunction<MemoryAddress, ValueLayout.OfAddress> { }
275 
276         interface OfByteArray extends AllocationFunction<byte[], ValueLayout.OfByte> { }
277         interface OfCharArray extends AllocationFunction<char[], ValueLayout.OfChar> { }
278         interface OfShortArray extends AllocationFunction<short[], ValueLayout.OfShort> { }
279         interface OfIntArray extends AllocationFunction<int[], ValueLayout.OfInt> { }
280         interface OfFloatArray extends AllocationFunction<float[], ValueLayout.OfFloat> { }
281         interface OfLongArray extends AllocationFunction<long[], ValueLayout.OfLong> { }
282         interface OfDoubleArray extends AllocationFunction<double[], ValueLayout.OfDouble> { }
283     }
284 
285     enum AllocationFactory {
286         ARENA_BOUNDED(true, SegmentAllocator::newNativeArena),
287         ARENA_UNBOUNDED(false, (size, scope) -> SegmentAllocator.newNativeArena(scope)),
288         NATIVE_ALLOCATOR(false, (size, scope) -> SegmentAllocator.nativeAllocator(scope)),
289         IMPLICIT_ALLOCATOR(false, (size, scope) -> SegmentAllocator.implicitAllocator());
290 
291         private final boolean isBound;
292         private final BiFunction<Long, ResourceScope, SegmentAllocator> factory;
293 
294         AllocationFactory(boolean isBound, BiFunction<Long, ResourceScope, SegmentAllocator> factory) {
295             this.isBound = isBound;
296             this.factory = factory;
297         }
298 
299         SegmentAllocator allocator(long size, ResourceScope scope) {
300             return factory.apply(size, scope);
301         }
302 
303         public boolean isBound() {
304             return isBound;
305         }



306     }
307 
308     interface ToArrayHelper<T> {
309         T array();
310         T toArray(MemorySegment segment, ValueLayout layout);
311 
312         ToArrayHelper<byte[]> toByteArray = new ToArrayHelper<>() {
313             @Override
314             public byte[] array() {
315                 return new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
316             }
317 
318             @Override
319             public byte[] toArray(MemorySegment segment, ValueLayout layout) {
320                 ByteBuffer buffer = segment.asByteBuffer().order(layout.order());
321                 byte[] found = new byte[buffer.limit()];
322                 buffer.get(found);
323                 return found;
324             }
325         };
326 
327         ToArrayHelper<char[]> toCharArray = new ToArrayHelper<>() {
328             @Override
329             public char[] array() {
330                 return new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
331             }
332 
333             @Override
334             public char[] toArray(MemorySegment segment, ValueLayout layout) {
335                 CharBuffer buffer = segment.asByteBuffer().order(layout.order()).asCharBuffer();
336                 char[] found = new char[buffer.limit()];
337                 buffer.get(found);
338                 return found;
339             }
340         };
341 
342         ToArrayHelper<short[]> toShortArray = new ToArrayHelper<>() {
343             @Override
344             public short[] array() {
345                 return new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
346             }
347 
348             @Override
349             public short[] toArray(MemorySegment segment, ValueLayout layout) {
350                 ShortBuffer buffer = segment.asByteBuffer().order(layout.order()).asShortBuffer();
351                 short[] found = new short[buffer.limit()];
352                 buffer.get(found);
353                 return found;
354             }
355         };
356 
357         ToArrayHelper<int[]> toIntArray = new ToArrayHelper<>() {
358             @Override
359             public int[] array() {
360                 return new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
361             }

400         };
401 
402         ToArrayHelper<double[]> toDoubleArray = new ToArrayHelper<>() {
403             @Override
404             public double[] array() {
405                 return new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
406             }
407 
408             @Override
409             public double[] toArray(MemorySegment segment, ValueLayout layout) {
410                 DoubleBuffer buffer = segment.asByteBuffer().order(layout.order()).asDoubleBuffer();
411                 double[] found = new double[buffer.limit()];
412                 buffer.get(found);
413                 return found;
414             }
415         };
416 
417         ToArrayHelper<MemoryAddress[]> toAddressArray = new ToArrayHelper<>() {
418             @Override
419             public MemoryAddress[] array() {
420                 return switch ((int) ValueLayout.ADDRESS.byteSize()) {
421                     case 4 -> wrap(toIntArray.array());
422                     case 8 -> wrap(toLongArray.array());
423                     default -> throw new IllegalStateException("Cannot get here");
424                 };
425             }
426 
427             @Override
428             public MemoryAddress[] toArray(MemorySegment segment, ValueLayout layout) {
429                 return switch ((int)layout.byteSize()) {
430                     case 4 -> wrap(toIntArray.toArray(segment, layout));
431                     case 8 -> wrap(toLongArray.toArray(segment, layout));
432                     default -> throw new IllegalStateException("Cannot get here");
433                 };
434             }
435 
436             private MemoryAddress[] wrap(int[] ints) {
437                 return IntStream.of(ints).mapToObj(MemoryAddress::ofLong).toArray(MemoryAddress[]::new);
438             }
439 
440             private MemoryAddress[] wrap(long[] ints) {
< prev index next >