diff a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java
--- a/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java
+++ b/src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemorySegment.java
@@ -193,10 +193,36 @@
*/
static Spliterator spliterator(S segment, SequenceLayout layout) {
return AbstractMemorySegmentImpl.spliterator(segment, layout);
}
+ /**
+ * Fills a value into the given memory segment.
+ *
+ * More specifically, the given value is filled into each address of the + * segment. Equivalent to (but likely more efficient than) the following code: + * + *
+ *+ * byteHandle = MemoryLayout.ofSequence(MemoryLayouts.JAVA_BYTE) + * .varHandle(byte.class, MemoryLayout.PathElement.sequenceElement()); + * for (long l = 0; l < segment.byteSize(); l++) { + * byteHandle.set(segment.baseAddress(), l, value); + * }
+ * Fill can be useful to initialize or reset the memory of a segment.
+ *
+ * @param segment the segment to fill
+ * @param value the value to fill into the segment
+ * @throws IllegalStateException if the segment is not alive, or if access occurs from a thread other than the
+ * thread owning this segment
+ * @throws UnsupportedOperationException if this segment does not support the {@link #WRITE} access mode
+ * @throws NullPointerException if {@code segment == null}
+ */
+ static void fill(MemorySegment segment, byte value) {
+ AbstractMemorySegmentImpl.fill(segment, value);
+ }
+
/**
* The thread owning this segment.
* @return the thread owning this segment.
*/
Thread ownerThread();
diff a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java
--- a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java
+++ b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java
@@ -30,10 +30,11 @@
import jdk.incubator.foreign.SequenceLayout;
import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.access.foreign.MemorySegmentProxy;
import jdk.internal.access.foreign.UnmapperProxy;
+import jdk.internal.misc.Unsafe;
import jdk.internal.vm.annotation.ForceInline;
import sun.security.action.GetPropertyAction;
import java.lang.invoke.VarHandle;
import java.nio.ByteBuffer;
@@ -53,10 +54,12 @@
* are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and
* {@link MappedMemorySegmentImpl}.
*/
public abstract class AbstractMemorySegmentImpl implements MemorySegment, MemorySegmentProxy {
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
private static final boolean enableSmallSegments =
Boolean.parseBoolean(GetPropertyAction.privilegedGetProperty("jdk.incubator.foreign.SmallSegments", "true"));
final static int ACCESS_MASK = READ | WRITE | CLOSE | ACQUIRE | HANDOFF;
final static int FIRST_RESERVED_FLAG = 1 << 16; // upper 16 bits are reserved
@@ -111,10 +114,19 @@
}
return (Spliterator)new SegmentSplitter(sequenceLayout.elementLayout().byteSize(), sequenceLayout.elementCount().getAsLong(),
(AbstractMemorySegmentImpl)segment.withAccessModes(segment.accessModes() & ~CLOSE));
}
+ public static void fill(MemorySegment segment, byte value) {
+ AbstractMemorySegmentImpl segmentImpl = (AbstractMemorySegmentImpl) segment;
+ segmentImpl.checkValidState();
+ if (!segmentImpl.isSet(WRITE)) {
+ throw segmentImpl.unsupportedAccessMode(WRITE);
+ }
+ UNSAFE.setMemory(segmentImpl.base(), segmentImpl.min(), segmentImpl.length, value);
+ }
+
@Override
@ForceInline
public final MemoryAddress baseAddress() {
return new MemoryAddressImpl(this, 0);
}
diff a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java
--- a/test/jdk/java/foreign/TestSegments.java
+++ b/test/jdk/java/foreign/TestSegments.java
@@ -30,23 +30,24 @@
import jdk.incubator.foreign.MemoryLayout;
import jdk.incubator.foreign.MemoryLayouts;
import jdk.incubator.foreign.MemorySegment;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
-
import java.lang.invoke.VarHandle;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.LongFunction;
+import java.util.function.Supplier;
import java.util.stream.Stream;
-
+import static jdk.incubator.foreign.MemorySegment.WRITE;
import static org.testng.Assert.*;
public class TestSegments {
@Test(dataProvider = "badSizeAndAlignments", expectedExceptions = IllegalArgumentException.class)
@@ -159,10 +160,106 @@
assertTrue(shouldFail);
}
}
}
+ @DataProvider(name = "segmentFactories")
+ public Object[][] segmentFactories() {
+ List