undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
618
test/jdk/java/foreign/TestSegmentAllocators.java
Normal file
618
test/jdk/java/foreign/TestSegmentAllocators.java
Normal file
|
|
@ -0,0 +1,618 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @modules java.base/jdk.internal.foreign
|
||||
* @run testng/othervm TestSegmentAllocators
|
||||
*/
|
||||
|
||||
import java.lang.foreign.*;
|
||||
|
||||
import org.testng.annotations.*;
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.LongBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class TestSegmentAllocators {
|
||||
|
||||
final static int ELEMS = 128;
|
||||
|
||||
@Test(dataProvider = "scalarAllocations")
|
||||
@SuppressWarnings("unchecked")
|
||||
public <Z, L extends ValueLayout> void testAllocation(Z value, AllocationFactory allocationFactory, L layout, AllocationFunction<Z, L> allocationFunction, Function<MemoryLayout, VarHandle> handleFactory) {
|
||||
layout = (L)layout.withByteAlignment(layout.byteSize());
|
||||
L[] layouts = (L[])new ValueLayout[] {
|
||||
layout,
|
||||
layout.withByteAlignment(layout.byteAlignment() * 2),
|
||||
layout.withByteAlignment(layout.byteAlignment() * 4),
|
||||
layout.withByteAlignment(layout.byteAlignment() * 8)
|
||||
};
|
||||
for (L alignedLayout : layouts) {
|
||||
List<MemorySegment> addressList = new ArrayList<>();
|
||||
int elems = ELEMS / ((int)alignedLayout.byteAlignment() / (int)layout.byteAlignment());
|
||||
Arena[] arenas = {
|
||||
Arena.ofConfined(),
|
||||
Arena.ofShared()
|
||||
};
|
||||
for (Arena arena : arenas) {
|
||||
try (arena) {
|
||||
SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, arena);
|
||||
for (int i = 0; i < elems; i++) {
|
||||
MemorySegment address = allocationFunction.allocate(allocator, alignedLayout, value);
|
||||
assertEquals(address.byteSize(), alignedLayout.byteSize());
|
||||
addressList.add(address);
|
||||
VarHandle handle = handleFactory.apply(alignedLayout);
|
||||
assertEquals(value, handle.get(address, 0L));
|
||||
}
|
||||
boolean isBound = allocationFactory.isBound();
|
||||
try {
|
||||
allocationFunction.allocate(allocator, alignedLayout, value);
|
||||
assertFalse(isBound);
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
//failure is expected if bound
|
||||
assertTrue(isBound);
|
||||
}
|
||||
}
|
||||
// addresses should be invalid now
|
||||
for (MemorySegment address : addressList) {
|
||||
assertFalse(address.scope().isAlive());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final int SIZE_256M = 1024 * 1024 * 256;
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testReadOnlySlicingAllocator() {
|
||||
SegmentAllocator.slicingAllocator(MemorySegment.ofArray(new int[0]).asReadOnly());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testReadOnlyPrefixAllocator() {
|
||||
SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new int[0]).asReadOnly());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBigAllocationInUnboundedSession() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
for (int i = 8 ; i < SIZE_256M ; i *= 8) {
|
||||
SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(i * 2 + 1));
|
||||
MemorySegment address = allocator.allocate(i, i);
|
||||
//check size
|
||||
assertEquals(address.byteSize(), i);
|
||||
//check alignment
|
||||
assertEquals(address.address() % i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTooBigForBoundedArena() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(10));
|
||||
assertThrows(IndexOutOfBoundsException.class, () -> allocator.allocate(12));
|
||||
allocator.allocate(5);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
|
||||
public void testBadAllocationSize(SegmentAllocator allocator) {
|
||||
allocator.allocate(-1);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
|
||||
public void testBadAllocationAlignZero(SegmentAllocator allocator) {
|
||||
allocator.allocate(1, 0);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
|
||||
public void testBadAllocationAlignNeg(SegmentAllocator allocator) {
|
||||
allocator.allocate(1, -1);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
|
||||
public void testBadAllocationAlignNotPowerTwo(SegmentAllocator allocator) {
|
||||
allocator.allocate(1, 3);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
|
||||
public void testBadAllocationArrayNegSize(SegmentAllocator allocator) {
|
||||
allocator.allocate(ValueLayout.JAVA_BYTE, -1);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class)
|
||||
public void testBadAllocationArrayOverflow(SegmentAllocator allocator) {
|
||||
allocator.allocate(ValueLayout.JAVA_LONG, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = OutOfMemoryError.class)
|
||||
public void testBadArenaNullReturn() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
arena.allocate(Long.MAX_VALUE, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class,
|
||||
expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*")
|
||||
public void testArenaAllocateFromHeapSegment() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
var heapSegment = MemorySegment.ofArray(new int[]{1});
|
||||
arena.allocateFrom(ValueLayout.ADDRESS, heapSegment);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class,
|
||||
expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*")
|
||||
public void testAllocatorAllocateFromHeapSegment() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
SegmentAllocator allocator = SegmentAllocator.prefixAllocator(arena.allocate(16));
|
||||
var heapSegment = MemorySegment.ofArray(new int[]{1});
|
||||
allocator.allocateFrom(ValueLayout.ADDRESS, heapSegment);
|
||||
}
|
||||
}
|
||||
|
||||
// Invariant checking tests for the SegmentAllocator method:
|
||||
// MemorySegment allocateFrom(ValueLayout elementLayout,
|
||||
// MemorySegment source,
|
||||
// ValueLayout sourceElementLayout,
|
||||
// long sourceOffset,
|
||||
// long elementCount) {
|
||||
@Test
|
||||
public void testAllocatorAllocateFromArguments() {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
var sourceElements = 2;
|
||||
var source = arena.allocate(ValueLayout.JAVA_LONG, sourceElements);
|
||||
var elementLayout = ValueLayout.JAVA_INT;
|
||||
var sourceElementLayout = ValueLayout.JAVA_INT;
|
||||
|
||||
// IllegalArgumentException if {@code elementLayout.byteSize() != sourceElementLayout.byteSize()}
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, ValueLayout.JAVA_BYTE, 0, 1)
|
||||
);
|
||||
|
||||
// IllegalArgumentException if source segment/offset
|
||||
// are <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
|
||||
// in the source element layout
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source.asSlice(1), sourceElementLayout, 0, 1)
|
||||
);
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, 1, 1)
|
||||
);
|
||||
|
||||
// IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout.withByteAlignment(elementLayout.byteAlignment() * 2), source, sourceElementLayout, 1, 1)
|
||||
);
|
||||
|
||||
// IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated
|
||||
// with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive}
|
||||
// This is tested in TestScopedOperations
|
||||
|
||||
// WrongThreadException if this method is called from a thread {@code T},
|
||||
// such that {@code source.isAccessibleBy(T) == false}
|
||||
CompletableFuture<Arena> future = CompletableFuture.supplyAsync(Arena::ofConfined);
|
||||
try {
|
||||
Arena otherThreadArena = future.get();
|
||||
assertThrows(WrongThreadException.class, () ->
|
||||
otherThreadArena.allocateFrom(elementLayout, source, sourceElementLayout, 0, 1)
|
||||
);
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
fail("Unable to create arena", e);
|
||||
}
|
||||
|
||||
// IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, Long.MAX_VALUE)
|
||||
);
|
||||
|
||||
// IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())}
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, source.byteSize() - (1 * sourceElementLayout.byteAlignment()) + elementLayout.byteSize(), 1)
|
||||
);
|
||||
|
||||
// IndexOutOfBoundsException if {@code sourceOffset < 0}
|
||||
assertThrows(IndexOutOfBoundsException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, -elementLayout.byteSize(), 1)
|
||||
);
|
||||
|
||||
// IllegalArgumentException if {@code elementCount < 0}
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, -1)
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testArrayAllocateDelegation() {
|
||||
AtomicInteger calls = new AtomicInteger();
|
||||
SegmentAllocator allocator = new SegmentAllocator() {
|
||||
@Override
|
||||
public MemorySegment allocate(long bytesSize, long byteAlignment) {
|
||||
return MemorySegment.NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source, ValueLayout sourceElementLayout, long sourceOffset, long elementCount) {
|
||||
calls.incrementAndGet();
|
||||
return MemorySegment.NULL;
|
||||
}
|
||||
};
|
||||
allocator.allocateFrom(ValueLayout.JAVA_BYTE);
|
||||
allocator.allocateFrom(ValueLayout.JAVA_SHORT);
|
||||
allocator.allocateFrom(ValueLayout.JAVA_CHAR);
|
||||
allocator.allocateFrom(ValueLayout.JAVA_INT);
|
||||
allocator.allocateFrom(ValueLayout.JAVA_FLOAT);
|
||||
allocator.allocateFrom(ValueLayout.JAVA_LONG);
|
||||
allocator.allocateFrom(ValueLayout.JAVA_DOUBLE);
|
||||
assertEquals(calls.get(), 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringAllocateDelegation() {
|
||||
AtomicInteger calls = new AtomicInteger();
|
||||
SegmentAllocator allocator = new SegmentAllocator() {
|
||||
@Override
|
||||
public MemorySegment allocate(long byteSize, long byteAlignment) {
|
||||
return Arena.ofAuto().allocate(byteSize, byteAlignment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySegment allocate(long size) {
|
||||
calls.incrementAndGet();
|
||||
return allocate(size, 1);
|
||||
};
|
||||
};
|
||||
allocator.allocateFrom("Hello");
|
||||
assertEquals(calls.get(), 1);
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "arrayAllocations")
|
||||
public <Z> void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Object, ValueLayout> allocationFunction, ToArrayHelper<Z> arrayHelper) {
|
||||
Z arr = arrayHelper.array();
|
||||
Arena[] arenas = {
|
||||
Arena.ofConfined(),
|
||||
Arena.ofShared()
|
||||
};
|
||||
for (Arena arena : arenas) {
|
||||
try (arena) {
|
||||
SegmentAllocator allocator = allocationFactory.allocator(100, arena);
|
||||
MemorySegment address = allocationFunction.allocate(allocator, layout, arr);
|
||||
Z found = arrayHelper.toArray(address, layout);
|
||||
assertEquals(found, arr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "arrayAllocations")
|
||||
public <Z> void testPredicatesAndCommands(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction<Object, ValueLayout> allocationFunction, ToArrayHelper<Z> arrayHelper) {
|
||||
Z arr = arrayHelper.array();
|
||||
Arena[] arenas = {
|
||||
Arena.ofConfined(),
|
||||
Arena.ofShared()
|
||||
};
|
||||
for (Arena arena : arenas) {
|
||||
try (arena) {
|
||||
SegmentAllocator allocator = allocationFactory.allocator(100, arena);
|
||||
MemorySegment segment = allocationFunction.allocate(allocator, layout, arr);
|
||||
assertThrows(UnsupportedOperationException.class, segment::load);
|
||||
assertThrows(UnsupportedOperationException.class, segment::unload);
|
||||
assertThrows(UnsupportedOperationException.class, segment::isLoaded);
|
||||
assertThrows(UnsupportedOperationException.class, segment::force);
|
||||
assertFalse(segment.isMapped());
|
||||
assertTrue(segment.isNative());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider(name = "scalarAllocations")
|
||||
static Object[][] scalarAllocations() {
|
||||
List<Object[]> scalarAllocations = new ArrayList<>();
|
||||
for (AllocationFactory factory : AllocationFactory.values()) {
|
||||
scalarAllocations.add(new Object[] { (byte)42, factory, ValueLayout.JAVA_BYTE,
|
||||
(AllocationFunction.OfByte) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfShort) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfChar) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { 42, factory,
|
||||
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfInt) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfFloat) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfLong) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfDouble) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfAddress) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
|
||||
scalarAllocations.add(new Object[] { (short)42, factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfShort) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { (char)42, factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfChar) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { 42, factory,
|
||||
ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfInt) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { 42f, factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfFloat) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { 42L, factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfLong) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfDouble) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfAddress) SegmentAllocator::allocateFrom,
|
||||
(Function<MemoryLayout, VarHandle>)l -> l.varHandle() });
|
||||
}
|
||||
return scalarAllocations.toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
@DataProvider(name = "arrayAllocations")
|
||||
static Object[][] arrayAllocations() {
|
||||
List<Object[]> arrayAllocations = new ArrayList<>();
|
||||
for (AllocationFactory factory : AllocationFactory.values()) {
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_BYTE,
|
||||
(AllocationFunction.OfByteArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toByteArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfCharArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toCharArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfShortArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toShortArray });
|
||||
arrayAllocations.add(new Object[] { factory,
|
||||
ValueLayout.JAVA_INT.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfIntArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toIntArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfFloatArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toFloatArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfLongArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toLongArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN),
|
||||
(AllocationFunction.OfDoubleArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toDoubleArray });
|
||||
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_CHAR.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfCharArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toCharArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_SHORT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfShortArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toShortArray });
|
||||
arrayAllocations.add(new Object[] { factory,
|
||||
ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfIntArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toIntArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_FLOAT.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfFloatArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toFloatArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_LONG.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfLongArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toLongArray });
|
||||
arrayAllocations.add(new Object[] { factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN),
|
||||
(AllocationFunction.OfDoubleArray) SegmentAllocator::allocateFrom,
|
||||
ToArrayHelper.toDoubleArray });
|
||||
};
|
||||
return arrayAllocations.toArray(Object[][]::new);
|
||||
}
|
||||
|
||||
interface AllocationFunction<X, L extends ValueLayout> {
|
||||
MemorySegment allocate(SegmentAllocator allocator, L layout, X value);
|
||||
|
||||
interface OfByte extends AllocationFunction<Byte, ValueLayout.OfByte> { }
|
||||
interface OfBoolean extends AllocationFunction<Boolean, ValueLayout.OfBoolean> { }
|
||||
interface OfChar extends AllocationFunction<Character, ValueLayout.OfChar> { }
|
||||
interface OfShort extends AllocationFunction<Short, ValueLayout.OfShort> { }
|
||||
interface OfInt extends AllocationFunction<Integer, ValueLayout.OfInt> { }
|
||||
interface OfFloat extends AllocationFunction<Float, ValueLayout.OfFloat> { }
|
||||
interface OfLong extends AllocationFunction<Long, ValueLayout.OfLong> { }
|
||||
interface OfDouble extends AllocationFunction<Double, ValueLayout.OfDouble> { }
|
||||
interface OfAddress extends AllocationFunction<MemorySegment, AddressLayout> { }
|
||||
|
||||
interface OfByteArray extends AllocationFunction<byte[], ValueLayout.OfByte> { }
|
||||
interface OfCharArray extends AllocationFunction<char[], ValueLayout.OfChar> { }
|
||||
interface OfShortArray extends AllocationFunction<short[], ValueLayout.OfShort> { }
|
||||
interface OfIntArray extends AllocationFunction<int[], ValueLayout.OfInt> { }
|
||||
interface OfFloatArray extends AllocationFunction<float[], ValueLayout.OfFloat> { }
|
||||
interface OfLongArray extends AllocationFunction<long[], ValueLayout.OfLong> { }
|
||||
interface OfDoubleArray extends AllocationFunction<double[], ValueLayout.OfDouble> { }
|
||||
}
|
||||
|
||||
enum AllocationFactory {
|
||||
SLICING(true, (size, arena) -> {
|
||||
return SegmentAllocator.slicingAllocator(arena.allocate(size, 1));
|
||||
});
|
||||
|
||||
private final boolean isBound;
|
||||
private final BiFunction<Long, Arena, SegmentAllocator> factory;
|
||||
|
||||
AllocationFactory(boolean isBound, BiFunction<Long, Arena, SegmentAllocator> factory) {
|
||||
this.isBound = isBound;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
SegmentAllocator allocator(long size, Arena arena) {
|
||||
return factory.apply(size, arena);
|
||||
}
|
||||
|
||||
public boolean isBound() {
|
||||
return isBound;
|
||||
}
|
||||
}
|
||||
|
||||
interface ToArrayHelper<T> {
|
||||
T array();
|
||||
T toArray(MemorySegment segment, ValueLayout layout);
|
||||
|
||||
ToArrayHelper<byte[]> toByteArray = new ToArrayHelper<>() {
|
||||
@Override
|
||||
public byte[] array() {
|
||||
return new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toArray(MemorySegment segment, ValueLayout layout) {
|
||||
ByteBuffer buffer = segment.asByteBuffer().order(layout.order());
|
||||
byte[] found = new byte[buffer.limit()];
|
||||
buffer.get(found);
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
ToArrayHelper<char[]> toCharArray = new ToArrayHelper<>() {
|
||||
@Override
|
||||
public char[] array() {
|
||||
return new char[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] toArray(MemorySegment segment, ValueLayout layout) {
|
||||
CharBuffer buffer = segment.asByteBuffer().order(layout.order()).asCharBuffer();
|
||||
char[] found = new char[buffer.limit()];
|
||||
buffer.get(found);
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
ToArrayHelper<short[]> toShortArray = new ToArrayHelper<>() {
|
||||
@Override
|
||||
public short[] array() {
|
||||
return new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public short[] toArray(MemorySegment segment, ValueLayout layout) {
|
||||
ShortBuffer buffer = segment.asByteBuffer().order(layout.order()).asShortBuffer();
|
||||
short[] found = new short[buffer.limit()];
|
||||
buffer.get(found);
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
ToArrayHelper<int[]> toIntArray = new ToArrayHelper<>() {
|
||||
@Override
|
||||
public int[] array() {
|
||||
return new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] toArray(MemorySegment segment, ValueLayout layout) {
|
||||
IntBuffer buffer = segment.asByteBuffer().order(layout.order()).asIntBuffer();
|
||||
int[] found = new int[buffer.limit()];
|
||||
buffer.get(found);
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
ToArrayHelper<float[]> toFloatArray = new ToArrayHelper<>() {
|
||||
@Override
|
||||
public float[] array() {
|
||||
return new float[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] toArray(MemorySegment segment, ValueLayout layout) {
|
||||
FloatBuffer buffer = segment.asByteBuffer().order(layout.order()).asFloatBuffer();
|
||||
float[] found = new float[buffer.limit()];
|
||||
buffer.get(found);
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
ToArrayHelper<long[]> toLongArray = new ToArrayHelper<>() {
|
||||
@Override
|
||||
public long[] array() {
|
||||
return new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] toArray(MemorySegment segment, ValueLayout layout) {
|
||||
LongBuffer buffer = segment.asByteBuffer().order(layout.order()).asLongBuffer();
|
||||
long[] found = new long[buffer.limit()];
|
||||
buffer.get(found);
|
||||
return found;
|
||||
}
|
||||
};
|
||||
|
||||
ToArrayHelper<double[]> toDoubleArray = new ToArrayHelper<>() {
|
||||
@Override
|
||||
public double[] array() {
|
||||
return new double[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
}
|
||||
|
||||
@Override
|
||||
public double[] toArray(MemorySegment segment, ValueLayout layout) {
|
||||
DoubleBuffer buffer = segment.asByteBuffer().order(layout.order()).asDoubleBuffer();
|
||||
double[] found = new double[buffer.limit()];
|
||||
buffer.get(found);
|
||||
return found;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@DataProvider(name = "allocators")
|
||||
static Object[][] allocators() {
|
||||
return new Object[][] {
|
||||
{ SegmentAllocator.prefixAllocator(Arena.global().allocate(10, 1)) },
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue