Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8246053: Add a mask for default access modesAdd a default access mode flag #188

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -396,8 +396,8 @@
* buffer. The segment starts relative to the buffer's position (inclusive)
* and ends relative to the buffer's limit (exclusive).
* <p>
* The segment will feature all <a href="#access-modes">access modes</a>, unless the given
* buffer is {@linkplain ByteBuffer#isReadOnly() read-only} in which case the segment will
* The segment will feature all <a href="#access-modes">access modes</a> (see {@link #ALL_ACCESS}),
* unless the given buffer is {@linkplain ByteBuffer#isReadOnly() read-only} in which case the segment will
* not feature the {@link #WRITE} access mode.
* <p>
* The resulting memory segment keeps a reference to the backing buffer, to ensure it remains <em>reachable</em>
@@ -414,7 +414,8 @@ static MemorySegment ofByteBuffer(ByteBuffer bb) {
* Creates a new array memory segment that models the memory associated with a given heap-allocated byte array.
* <p>
* The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>
* (see {@link #ALL_ACCESS}).
*
* @param arr the primitive array backing the array memory segment.
* @return a new array memory segment.
@@ -427,7 +428,8 @@ static MemorySegment ofArray(byte[] arr) {
* Creates a new array memory segment that models the memory associated with a given heap-allocated char array.
* <p>
* The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>
* (see {@link #ALL_ACCESS}).
*
* @param arr the primitive array backing the array memory segment.
* @return a new array memory segment.
@@ -440,7 +442,8 @@ static MemorySegment ofArray(char[] arr) {
* Creates a new array memory segment that models the memory associated with a given heap-allocated short array.
* <p>
* The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>
* (see {@link #ALL_ACCESS}).
*
* @param arr the primitive array backing the array memory segment.
* @return a new array memory segment.
@@ -466,7 +469,8 @@ static MemorySegment ofArray(int[] arr) {
* Creates a new array memory segment that models the memory associated with a given heap-allocated float array.
* <p>
* The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>
* (see {@link #ALL_ACCESS}).
*
* @param arr the primitive array backing the array memory segment.
* @return a new array memory segment.
@@ -479,7 +483,8 @@ static MemorySegment ofArray(float[] arr) {
* Creates a new array memory segment that models the memory associated with a given heap-allocated long array.
* <p>
* The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>
* (see {@link #ALL_ACCESS}).
*
* @param arr the primitive array backing the array memory segment.
* @return a new array memory segment.
@@ -492,7 +497,8 @@ static MemorySegment ofArray(long[] arr) {
* Creates a new array memory segment that models the memory associated with a given heap-allocated double array.
* <p>
* The resulting memory segment keeps a reference to the backing array, to ensure it remains <em>reachable</em>
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>.
* for the life-time of the segment. The segment will feature all <a href="#access-modes">access modes</a>
* (see {@link #ALL_ACCESS}).
*
* @param arr the primitive array backing the array memory segment.
* @return a new array memory segment.
@@ -544,9 +550,9 @@ static MemorySegment allocateNative(long bytesSize) {
/**
* Creates a new mapped memory segment that models a memory-mapped region of a file from a given path.
* <p>
* The segment will feature all <a href="#access-modes">access modes</a>, unless the given mapping mode
* is {@linkplain FileChannel.MapMode#READ_ONLY READ_ONLY}, in which case the segment will not feature
* the {@link #WRITE} access mode.
* The segment will feature all <a href="#access-modes">access modes</a> (see {@link #ALL_ACCESS}),
* unless the given mapping mode is {@linkplain FileChannel.MapMode#READ_ONLY READ_ONLY}, in which case
* the segment will not feature the {@link #WRITE} access mode.
*
* @implNote When obtaining a mapped segment from a newly created file, the initialization state of the contents of the block
* of mapped memory associated with the returned mapped memory segment is unspecified and should not be relied upon.
@@ -568,7 +574,8 @@ static MappedMemorySegment mapFromPath(Path path, long bytesOffset, long bytesSi

/**
* Creates a new native memory segment that models a newly allocated block of off-heap memory with given size and
* alignment constraint (in bytes). The segment will feature all <a href="#access-modes">access modes</a>.
* alignment constraint (in bytes). The segment will feature all <a href="#access-modes">access modes</a>
* (see {@link #ALL_ACCESS}).
*
* @implNote The block of off-heap memory associated with the returned native memory segment is initialized to zero.
* Moreover, a client is responsible to call the {@link MemorySegment#close()} on a native memory segment,
@@ -598,7 +605,8 @@ static MemorySegment allocateNative(long bytesSize, long alignmentBytes) {
* bounds, and can therefore be closed; closing such a segment can optionally result in calling an user-provided cleanup
* action. This method can be very useful when interacting with custom native memory sources (e.g. custom allocators,
* GPU memory, etc.), where an address to some underlying memory region is typically obtained from native code
* (often as a plain {@code long} value). The segment will feature all <a href="#access-modes">access modes</a>.
* (often as a plain {@code long} value). The segment will feature all <a href="#access-modes">access modes</a>
* (see {@link #ALL_ACCESS}).
* <p>
* This method is <em>restricted</em>. Restricted method are unsafe, and, if used incorrectly, their use might crash
* the JVM crash or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
@@ -666,4 +674,11 @@ static MemorySegment ofNativeRestricted(MemoryAddress addr, long bytesSize, Thre
* @see MemorySegment#withAccessModes(int)
*/
int HANDOFF = ACQUIRE << 1;

/**
* Default access mode; this is a union of all the access modes supported by memory segments.
* @see MemorySegment#accessModes()
* @see MemorySegment#withAccessModes(int)
*/
int ALL_ACCESS = READ | WRITE | CLOSE | ACQUIRE | HANDOFF;
}
@@ -64,11 +64,9 @@
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
final static int SMALL = FIRST_RESERVED_FLAG;
final static long NONCE = new Random().nextLong();
final static int DEFAULT_MASK = READ | WRITE | CLOSE | ACQUIRE | HANDOFF;

final static JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();

@@ -93,8 +91,8 @@

static int defaultAccessModes(long size) {
return (enableSmallSegments && size < Integer.MAX_VALUE) ?
DEFAULT_MASK | SMALL :
DEFAULT_MASK;
ALL_ACCESS | SMALL :
ALL_ACCESS;
}

@Override
@@ -192,7 +190,7 @@ public final ByteBuffer asByteBuffer() {

@Override
public final int accessModes() {
return mask & ACCESS_MASK;
return mask & ALL_ACCESS;
}

@Override
@@ -216,7 +214,7 @@ public AbstractMemorySegmentImpl withAccessModes(int accessModes) {
if ((~accessModes() & accessModes) != 0) {
throw new IllegalArgumentException("Cannot acquire more access modes");
}
return dup(0, length, (mask & ~ACCESS_MASK) | accessModes, scope);
return dup(0, length, (mask & ~ALL_ACCESS) | accessModes, scope);
}

@Override
@@ -226,7 +224,7 @@ public boolean hasAccessModes(int accessModes) {
}

private void checkAccessModes(int accessModes) {
if ((accessModes & ~ACCESS_MASK) != 0) {
if ((accessModes & ~ALL_ACCESS) != 0) {
throw new IllegalArgumentException("Invalid access modes");
}
}
@@ -239,18 +239,16 @@ public void testChannel() throws Throwable {
}
}

static final int ALL_ACCESS_MODES = READ | WRITE | CLOSE | ACQUIRE | HANDOFF;

@Test
public void testDefaultAccessModesMappedSegment() throws Throwable {
try (MappedMemorySegment segment = MemorySegment.mapFromPath(tempPath, 0L, 8, FileChannel.MapMode.READ_WRITE)) {
assertTrue(segment.hasAccessModes(ALL_ACCESS_MODES));
assertEquals(segment.accessModes(), ALL_ACCESS_MODES);
assertTrue(segment.hasAccessModes(ALL_ACCESS));
assertEquals(segment.accessModes(), ALL_ACCESS);
}

try (MappedMemorySegment segment = MemorySegment.mapFromPath(tempPath, 0L, 8, FileChannel.MapMode.READ_ONLY)) {
assertTrue(segment.hasAccessModes(ALL_ACCESS_MODES & ~WRITE));
assertEquals(segment.accessModes(), ALL_ACCESS_MODES& ~WRITE);
assertTrue(segment.hasAccessModes(ALL_ACCESS & ~WRITE));
assertEquals(segment.accessModes(), ALL_ACCESS & ~WRITE);
}
}

@@ -521,14 +519,14 @@ public void testCopyNativeToHeap(Consumer<MemoryAddress> checker, Consumer<Memor
public void testDefaultAccessModesOfBuffer() {
ByteBuffer rwBuffer = ByteBuffer.wrap(new byte[4]);
try (MemorySegment segment = MemorySegment.ofByteBuffer(rwBuffer)) {
assertTrue(segment.hasAccessModes(ALL_ACCESS_MODES));
assertEquals(segment.accessModes(), ALL_ACCESS_MODES);
assertTrue(segment.hasAccessModes(ALL_ACCESS));
assertEquals(segment.accessModes(), ALL_ACCESS);
}

ByteBuffer roBuffer = rwBuffer.asReadOnlyBuffer();
try (MemorySegment segment = MemorySegment.ofByteBuffer(roBuffer)) {
assertTrue(segment.hasAccessModes(ALL_ACCESS_MODES & ~WRITE));
assertEquals(segment.accessModes(), ALL_ACCESS_MODES & ~WRITE);
assertTrue(segment.hasAccessModes(ALL_ACCESS & ~WRITE));
assertEquals(segment.accessModes(), ALL_ACCESS & ~WRITE);
}
}

@@ -172,16 +172,14 @@ public void testNativeCapacity(Function<ByteBuffer, Buffer> bufferFunction, int
}
}

static final int ALL_ACCESS_MODES = READ | WRITE | CLOSE | ACQUIRE | HANDOFF;

@Test
public void testDefaultAccessModes() {
MemoryAddress addr = MemoryAddress.ofLong(allocate(12));
MemorySegment mallocSegment = MemorySegment.ofNativeRestricted(addr, 12, null,
() -> free(addr.toRawLongValue()), null);
try (MemorySegment segment = mallocSegment) {
assertTrue(segment.hasAccessModes(ALL_ACCESS_MODES));
assertEquals(segment.accessModes(), ALL_ACCESS_MODES);
assertTrue(segment.hasAccessModes(ALL_ACCESS));
assertEquals(segment.accessModes(), ALL_ACCESS);
}
}

@@ -146,13 +146,11 @@ public void testSlices() {
}
}

static final int ALL_ACCESS_MODES = READ | WRITE | CLOSE | ACQUIRE | HANDOFF;

@Test(dataProvider = "segmentFactories")
public void testAccessModesOfFactories(Supplier<MemorySegment> memorySegmentSupplier) {
try (MemorySegment segment = memorySegmentSupplier.get()) {
assertTrue(segment.hasAccessModes(ALL_ACCESS_MODES));
assertEquals(segment.accessModes(), ALL_ACCESS_MODES);
assertTrue(segment.hasAccessModes(ALL_ACCESS));
assertEquals(segment.accessModes(), ALL_ACCESS);
}
}

@@ -205,15 +205,13 @@ protected Long compute() {
};
}

static final int ALL_ACCESS_MODES = READ | WRITE | CLOSE | ACQUIRE | HANDOFF;

@DataProvider(name = "accessScenarios")
public Object[][] accessScenarios() {
SequenceLayout layout = MemoryLayout.ofSequence(16, MemoryLayouts.JAVA_INT);
var mallocSegment = MemorySegment.allocateNative(layout);

Map<Supplier<Spliterator<MemorySegment>>,Integer> l = Map.of(
() -> spliterator(mallocSegment.withAccessModes(ALL_ACCESS_MODES), layout), ALL_ACCESS_MODES,
() -> spliterator(mallocSegment.withAccessModes(ALL_ACCESS), layout), ALL_ACCESS,
() -> spliterator(mallocSegment.withAccessModes(0), layout), 0,
() -> spliterator(mallocSegment.withAccessModes(READ), layout), READ,
() -> spliterator(mallocSegment.withAccessModes(CLOSE), layout), 0,