8282191: Implementation of Foreign Function & Memory API (Preview)

Reviewed-by: erikj, jvernee, psandoz, dholmes, mchung
This commit is contained in:
Maurizio Cimadamore 2022-05-12 16:17:45 +00:00
parent 3be394e160
commit 2c5d136260
303 changed files with 33474 additions and 9186 deletions

View file

@ -27,15 +27,17 @@ package java.nio;
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.foreign.AbstractMemorySegmentImpl;
import jdk.internal.foreign.MemorySessionImpl;
import jdk.internal.misc.ScopedMemoryAccess;
import jdk.internal.misc.ScopedMemoryAccess.Scope;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM.BufferPool;
import jdk.internal.vm.annotation.ForceInline;
import java.io.FileDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySession;
import java.util.Objects;
import java.util.Spliterator;
@ -225,12 +227,12 @@ public abstract sealed class Buffer
long address;
// Used by buffers generated by the memory access API (JEP-370)
final MemorySegmentProxy segment;
final MemorySegment segment;
// Creates a new buffer with given address and capacity.
//
Buffer(long addr, int cap, MemorySegmentProxy segment) {
Buffer(long addr, int cap, MemorySegment segment) {
this.address = addr;
this.capacity = cap;
this.segment = segment;
@ -239,7 +241,7 @@ public abstract sealed class Buffer
// Creates a new buffer with the given mark, position, limit, and capacity,
// after checking invariants.
//
Buffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) { // package-private
Buffer(int mark, int pos, int lim, int cap, MemorySegment segment) { // package-private
if (cap < 0)
throw createCapacityException(cap);
this.capacity = cap;
@ -758,20 +760,20 @@ public abstract sealed class Buffer
}
@ForceInline
final ScopedMemoryAccess.Scope scope() {
final MemorySessionImpl session() {
if (segment != null) {
return segment.scope();
return ((AbstractMemorySegmentImpl)segment).sessionImpl();
} else {
return null;
}
}
final void checkScope() {
ScopedMemoryAccess.Scope scope = scope();
if (scope != null) {
final void checkSession() {
MemorySessionImpl session = session();
if (session != null) {
try {
scope.checkValidState();
} catch (ScopedMemoryAccess.Scope.ScopedAccessError e) {
session.checkValidState();
} catch (ScopedMemoryAccess.ScopedAccessError e) {
throw new IllegalStateException("This segment is already closed");
}
}
@ -787,17 +789,17 @@ public abstract sealed class Buffer
}
@Override
public ByteBuffer newDirectByteBuffer(long addr, int cap, Object obj, MemorySegmentProxy segment) {
public ByteBuffer newDirectByteBuffer(long addr, int cap, Object obj, MemorySegment segment) {
return new DirectByteBuffer(addr, cap, obj, segment);
}
@Override
public ByteBuffer newMappedByteBuffer(UnmapperProxy unmapperProxy, long address, int cap, Object obj, MemorySegmentProxy segment) {
public ByteBuffer newMappedByteBuffer(UnmapperProxy unmapperProxy, long address, int cap, Object obj, MemorySegment segment) {
return new DirectByteBuffer(address, cap, obj, unmapperProxy.fileDescriptor(), unmapperProxy.isSync(), segment);
}
@Override
public ByteBuffer newHeapByteBuffer(byte[] hb, int offset, int capacity, MemorySegmentProxy segment) {
public ByteBuffer newHeapByteBuffer(byte[] hb, int offset, int capacity, MemorySegment segment) {
return new HeapByteBuffer(hb, -1, 0, capacity, capacity, offset, segment);
}
@ -821,21 +823,21 @@ public abstract sealed class Buffer
}
@Override
public MemorySegmentProxy bufferSegment(Buffer buffer) {
public MemorySegment bufferSegment(Buffer buffer) {
return buffer.segment;
}
@Override
public Runnable acquireScope(Buffer buffer, boolean async) {
var scope = buffer.scope();
if (scope == null) {
public Runnable acquireSession(Buffer buffer, boolean async) {
var session = buffer.session();
if (session == null) {
return null;
}
if (async && scope.ownerThread() != null) {
throw new IllegalStateException("Confined scope not supported");
if (async && session.ownerThread() != null) {
throw new IllegalStateException("Confined session not supported");
}
scope.acquire0();
return scope::release0;
session.acquire0();
return session::release0;
}
@Override

View file

@ -39,7 +39,7 @@ final class BufferMismatch {
if (length > 7) {
if (a.get(aOff) != b.get(bOff))
return 0;
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.scope(), b.scope(),
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.session(), b.session(),
a.base(), a.address + aOff,
b.base(), b.address + bOff,
length,
@ -63,7 +63,7 @@ final class BufferMismatch {
&& a.charRegionOrder() != null && b.charRegionOrder() != null) {
if (a.get(aOff) != b.get(bOff))
return 0;
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.scope(), b.scope(),
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.session(), b.session(),
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
length,
@ -83,7 +83,7 @@ final class BufferMismatch {
if (length > 3 && a.order() == b.order()) {
if (a.get(aOff) != b.get(bOff))
return 0;
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.scope(), b.scope(),
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.session(), b.session(),
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
length,
@ -103,7 +103,7 @@ final class BufferMismatch {
if (length > 1 && a.order() == b.order()) {
if (a.get(aOff) != b.get(bOff))
return 0;
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.scope(), b.scope(),
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.session(), b.session(),
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
length,
@ -122,7 +122,7 @@ final class BufferMismatch {
int i = 0;
if (length > 1 && a.order() == b.order()) {
if (Float.floatToRawIntBits(a.get(aOff)) == Float.floatToRawIntBits(b.get(bOff))) {
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.scope(), b.scope(),
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.session(), b.session(),
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
length,
@ -161,7 +161,7 @@ final class BufferMismatch {
if (length > 0 && a.order() == b.order()) {
if (a.get(aOff) != b.get(bOff))
return 0;
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.scope(), b.scope(),
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.session(), b.session(),
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
length,
@ -179,7 +179,7 @@ final class BufferMismatch {
int i = 0;
if (length > 0 && a.order() == b.order()) {
if (Double.doubleToRawLongBits(a.get(aOff)) == Double.doubleToRawLongBits(b.get(bOff))) {
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.scope(), b.scope(),
i = SCOPED_MEMORY_ACCESS.vectorizedMismatch(a.session(), b.session(),
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
length,

View file

@ -27,8 +27,8 @@
package java.nio;
import java.lang.foreign.MemorySegment;
import java.util.Objects;
import jdk.internal.access.foreign.MemorySegmentProxy;
import jdk.internal.misc.Unsafe;
#if[rw]
@ -49,7 +49,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
#end[rw]
ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb, MemorySegmentProxy segment) { // package-private
ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb, MemorySegment segment) { // package-private
#if[rw]
super(-1, 0,
bb.remaining() >> $LG_BYTES_PER_VALUE$,
@ -68,7 +68,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
ByteBufferAs$Type$Buffer$RW$$BO$(ByteBuffer bb,
int mark, int pos, int lim, int cap,
long addr, MemorySegmentProxy segment)
long addr, MemorySegment segment)
{
#if[rw]
super(mark, pos, lim, cap, segment);
@ -138,13 +138,13 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
}
public $type$ get() {
$memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(scope(), bb.hb, byteOffset(nextGetIndex()),
$memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(session(), bb.hb, byteOffset(nextGetIndex()),
{#if[boB]?true:false});
return $fromBits$(x);
}
public $type$ get(int i) {
$memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(scope(), bb.hb, byteOffset(checkIndex(i)),
$memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(session(), bb.hb, byteOffset(checkIndex(i)),
{#if[boB]?true:false});
return $fromBits$(x);
}
@ -162,7 +162,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
public $Type$Buffer put($type$ x) {
#if[rw]
$memtype$ y = $toBits$(x);
SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(scope(), bb.hb, byteOffset(nextPutIndex()), y,
SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(session(), bb.hb, byteOffset(nextPutIndex()), y,
{#if[boB]?true:false});
return this;
#else[rw]
@ -173,7 +173,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
public $Type$Buffer put(int i, $type$ x) {
#if[rw]
$memtype$ y = $toBits$(x);
SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(scope(), bb.hb, byteOffset(checkIndex(i)), y,
SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(session(), bb.hb, byteOffset(checkIndex(i)), y,
{#if[boB]?true:false});
return this;
#else[rw]

View file

@ -33,7 +33,7 @@ class XXX {
private $type$ get$Type$(long a) {
try {
$memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(scope(), null, a, bigEndian);
$memtype$ x = SCOPED_MEMORY_ACCESS.get$Memtype$Unaligned(session(), null, a, bigEndian);
return $fromBits$(x);
} finally {
Reference.reachabilityFence(this);
@ -62,7 +62,7 @@ class XXX {
#if[rw]
try {
$memtype$ y = $toBits$(x);
SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(scope(), null, a, y, bigEndian);
SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(session(), null, a, y, bigEndian);
} finally {
Reference.reachabilityFence(this);
}

View file

@ -28,10 +28,12 @@
package java.nio;
import java.io.FileDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySession;
import java.lang.ref.Reference;
import java.util.Objects;
import jdk.internal.access.foreign.MemorySegmentProxy;
import jdk.internal.misc.ScopedMemoryAccess.Scope;
import jdk.internal.foreign.MemorySessionImpl;
import jdk.internal.misc.ScopedMemoryAccess.ScopedAccessError;
import jdk.internal.misc.VM;
import jdk.internal.ref.Cleaner;
import sun.nio.ch.DirectBuffer;
@ -152,7 +154,7 @@ class Direct$Type$Buffer$RW$$BO$
// Invoked to construct a direct ByteBuffer referring to the block of
// memory. A given arbitrary object may also be attached to the buffer.
//
Direct$Type$Buffer(long addr, int cap, Object ob, MemorySegmentProxy segment) {
Direct$Type$Buffer(long addr, int cap, Object ob, MemorySegment segment) {
super(-1, 0, cap, cap, segment);
address = addr;
cleaner = null;
@ -162,7 +164,7 @@ class Direct$Type$Buffer$RW$$BO$
// Invoked to construct a direct ByteBuffer referring to the block of
// memory. A given arbitrary object may also be attached to the buffer.
//
Direct$Type$Buffer(long addr, int cap, Object ob, FileDescriptor fd, boolean isSync, MemorySegmentProxy segment) {
Direct$Type$Buffer(long addr, int cap, Object ob, FileDescriptor fd, boolean isSync, MemorySegment segment) {
super(-1, 0, cap, cap, fd, isSync, segment);
address = addr;
cleaner = null;
@ -185,7 +187,7 @@ class Direct$Type$Buffer$RW$$BO$
protected Direct$Type$Buffer$RW$(int cap, long addr,
FileDescriptor fd,
Runnable unmapper,
boolean isSync, MemorySegmentProxy segment)
boolean isSync, MemorySegment segment)
{
#if[rw]
super(-1, 0, cap, cap, fd, isSync, segment);
@ -207,7 +209,7 @@ class Direct$Type$Buffer$RW$$BO$
#if[byte]
FileDescriptor fd, boolean isSync,
#end[byte]
MemorySegmentProxy segment)
MemorySegment segment)
{
#if[rw]
super(mark, pos, lim, cap,
@ -306,14 +308,14 @@ class Direct$Type$Buffer$RW$$BO$
#if[rw]
public long address() {
Scope scope = scope();
if (scope != null) {
if (scope.ownerThread() == null) {
throw new UnsupportedOperationException("ByteBuffer derived from shared segments not supported");
MemorySessionImpl session = session();
if (session != null) {
if (session.ownerThread() == null && session.isCloseable()) {
throw new UnsupportedOperationException("ByteBuffer derived from closeable shared sessions not supported");
}
try {
scope.checkValidState();
} catch (Scope.ScopedAccessError e) {
session.checkValidState();
} catch (ScopedAccessError e) {
throw new IllegalStateException("This segment is already closed");
}
}
@ -326,7 +328,7 @@ class Direct$Type$Buffer$RW$$BO$
public $type$ get() {
try {
return $fromBits$($swap$(SCOPED_MEMORY_ACCESS.get$Swaptype$(scope(), null, ix(nextGetIndex()))));
return $fromBits$($swap$(SCOPED_MEMORY_ACCESS.get$Swaptype$(session(), null, ix(nextGetIndex()))));
} finally {
Reference.reachabilityFence(this);
}
@ -334,7 +336,7 @@ class Direct$Type$Buffer$RW$$BO$
public $type$ get(int i) {
try {
return $fromBits$($swap$(SCOPED_MEMORY_ACCESS.get$Swaptype$(scope(), null, ix(checkIndex(i)))));
return $fromBits$($swap$(SCOPED_MEMORY_ACCESS.get$Swaptype$(session(), null, ix(checkIndex(i)))));
} finally {
Reference.reachabilityFence(this);
}
@ -354,7 +356,7 @@ class Direct$Type$Buffer$RW$$BO$
public $Type$Buffer put($type$ x) {
#if[rw]
try {
SCOPED_MEMORY_ACCESS.put$Swaptype$(scope(), null, ix(nextPutIndex()), $swap$($toBits$(x)));
SCOPED_MEMORY_ACCESS.put$Swaptype$(session(), null, ix(nextPutIndex()), $swap$($toBits$(x)));
} finally {
Reference.reachabilityFence(this);
}
@ -367,7 +369,7 @@ class Direct$Type$Buffer$RW$$BO$
public $Type$Buffer put(int i, $type$ x) {
#if[rw]
try {
SCOPED_MEMORY_ACCESS.put$Swaptype$(scope(), null, ix(checkIndex(i)), $swap$($toBits$(x)));
SCOPED_MEMORY_ACCESS.put$Swaptype$(session(), null, ix(checkIndex(i)), $swap$($toBits$(x)));
} finally {
Reference.reachabilityFence(this);
}
@ -384,8 +386,8 @@ class Direct$Type$Buffer$RW$$BO$
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
try {
// null is passed as destination Scope to avoid checking scope() twice
SCOPED_MEMORY_ACCESS.copyMemory(scope(), null, null,
// null is passed as destination MemorySession to avoid checking session() twice
SCOPED_MEMORY_ACCESS.copyMemory(session(), null, null,
ix(pos), null, ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
} finally {
Reference.reachabilityFence(this);

View file

@ -27,8 +27,8 @@
package java.nio;
import java.lang.foreign.MemorySegment;
import java.util.Objects;
import jdk.internal.access.foreign.MemorySegmentProxy;
/**
#if[rw]
@ -66,7 +66,7 @@ class Heap$Type$Buffer$RW$
*/
#end[rw]
Heap$Type$Buffer$RW$(int cap, int lim, MemorySegmentProxy segment) { // package-private
Heap$Type$Buffer$RW$(int cap, int lim, MemorySegment segment) { // package-private
#if[rw]
super(-1, 0, lim, cap, new $type$[cap], 0, segment);
/*
@ -80,7 +80,7 @@ class Heap$Type$Buffer$RW$
#end[rw]
}
Heap$Type$Buffer$RW$($type$[] buf, int off, int len, MemorySegmentProxy segment) { // package-private
Heap$Type$Buffer$RW$($type$[] buf, int off, int len, MemorySegment segment) { // package-private
#if[rw]
super(-1, off, off + len, buf.length, buf, 0, segment);
/*
@ -96,7 +96,7 @@ class Heap$Type$Buffer$RW$
protected Heap$Type$Buffer$RW$($type$[] buf,
int mark, int pos, int lim, int cap,
int off, MemorySegmentProxy segment)
int off, MemorySegment segment)
{
#if[rw]
super(mark, pos, lim, cap, buf, off, segment);
@ -183,7 +183,7 @@ class Heap$Type$Buffer$RW$
#end[streamableType]
public $Type$Buffer get($type$[] dst, int offset, int length) {
checkScope();
checkSession();
Objects.checkFromIndexSize(offset, length, dst.length);
int pos = position();
if (length > limit() - pos)
@ -194,7 +194,7 @@ class Heap$Type$Buffer$RW$
}
public $Type$Buffer get(int index, $type$[] dst, int offset, int length) {
checkScope();
checkSession();
Objects.checkFromIndexSize(index, length, limit());
Objects.checkFromIndexSize(offset, length, dst.length);
System.arraycopy(hb, ix(index), dst, offset, length);
@ -231,7 +231,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer put($type$[] src, int offset, int length) {
#if[rw]
checkScope();
checkSession();
Objects.checkFromIndexSize(offset, length, src.length);
int pos = position();
if (length > limit() - pos)
@ -246,7 +246,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer put($Type$Buffer src) {
#if[rw]
checkScope();
checkSession();
super.put(src);
return this;
#else[rw]
@ -256,7 +256,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer put(int index, $Type$Buffer src, int offset, int length) {
#if[rw]
checkScope();
checkSession();
super.put(index, src, offset, length);
return this;
#else[rw]
@ -266,7 +266,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer put(int index, $type$[] src, int offset, int length) {
#if[rw]
checkScope();
checkSession();
Objects.checkFromIndexSize(index, length, limit());
Objects.checkFromIndexSize(offset, length, src.length);
System.arraycopy(src, offset, hb, ix(index), length);
@ -280,7 +280,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer put(String src, int start, int end) {
#if[rw]
checkScope();
checkSession();
int length = end - start;
Objects.checkFromIndexSize(start, length, src.length());
int pos = position();
@ -335,18 +335,18 @@ class Heap$Type$Buffer$RW$
#if[rw]
public char getChar() {
return SCOPED_MEMORY_ACCESS.getCharUnaligned(scope(), hb, byteOffset(nextGetIndex(2)), bigEndian);
return SCOPED_MEMORY_ACCESS.getCharUnaligned(session(), hb, byteOffset(nextGetIndex(2)), bigEndian);
}
public char getChar(int i) {
return SCOPED_MEMORY_ACCESS.getCharUnaligned(scope(), hb, byteOffset(checkIndex(i, 2)), bigEndian);
return SCOPED_MEMORY_ACCESS.getCharUnaligned(session(), hb, byteOffset(checkIndex(i, 2)), bigEndian);
}
#end[rw]
public $Type$Buffer putChar(char x) {
#if[rw]
SCOPED_MEMORY_ACCESS.putCharUnaligned(scope(), hb, byteOffset(nextPutIndex(2)), x, bigEndian);
SCOPED_MEMORY_ACCESS.putCharUnaligned(session(), hb, byteOffset(nextPutIndex(2)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -355,7 +355,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putChar(int i, char x) {
#if[rw]
SCOPED_MEMORY_ACCESS.putCharUnaligned(scope(), hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
SCOPED_MEMORY_ACCESS.putCharUnaligned(session(), hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -387,18 +387,18 @@ class Heap$Type$Buffer$RW$
#if[rw]
public short getShort() {
return SCOPED_MEMORY_ACCESS.getShortUnaligned(scope(), hb, byteOffset(nextGetIndex(2)), bigEndian);
return SCOPED_MEMORY_ACCESS.getShortUnaligned(session(), hb, byteOffset(nextGetIndex(2)), bigEndian);
}
public short getShort(int i) {
return SCOPED_MEMORY_ACCESS.getShortUnaligned(scope(), hb, byteOffset(checkIndex(i, 2)), bigEndian);
return SCOPED_MEMORY_ACCESS.getShortUnaligned(session(), hb, byteOffset(checkIndex(i, 2)), bigEndian);
}
#end[rw]
public $Type$Buffer putShort(short x) {
#if[rw]
SCOPED_MEMORY_ACCESS.putShortUnaligned(scope(), hb, byteOffset(nextPutIndex(2)), x, bigEndian);
SCOPED_MEMORY_ACCESS.putShortUnaligned(session(), hb, byteOffset(nextPutIndex(2)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -407,7 +407,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putShort(int i, short x) {
#if[rw]
SCOPED_MEMORY_ACCESS.putShortUnaligned(scope(), hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
SCOPED_MEMORY_ACCESS.putShortUnaligned(session(), hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -439,18 +439,18 @@ class Heap$Type$Buffer$RW$
#if[rw]
public int getInt() {
return SCOPED_MEMORY_ACCESS.getIntUnaligned(scope(), hb, byteOffset(nextGetIndex(4)), bigEndian);
return SCOPED_MEMORY_ACCESS.getIntUnaligned(session(), hb, byteOffset(nextGetIndex(4)), bigEndian);
}
public int getInt(int i) {
return SCOPED_MEMORY_ACCESS.getIntUnaligned(scope(), hb, byteOffset(checkIndex(i, 4)), bigEndian);
return SCOPED_MEMORY_ACCESS.getIntUnaligned(session(), hb, byteOffset(checkIndex(i, 4)), bigEndian);
}
#end[rw]
public $Type$Buffer putInt(int x) {
#if[rw]
SCOPED_MEMORY_ACCESS.putIntUnaligned(scope(), hb, byteOffset(nextPutIndex(4)), x, bigEndian);
SCOPED_MEMORY_ACCESS.putIntUnaligned(session(), hb, byteOffset(nextPutIndex(4)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -459,7 +459,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putInt(int i, int x) {
#if[rw]
SCOPED_MEMORY_ACCESS.putIntUnaligned(scope(), hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
SCOPED_MEMORY_ACCESS.putIntUnaligned(session(), hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -491,18 +491,18 @@ class Heap$Type$Buffer$RW$
#if[rw]
public long getLong() {
return SCOPED_MEMORY_ACCESS.getLongUnaligned(scope(), hb, byteOffset(nextGetIndex(8)), bigEndian);
return SCOPED_MEMORY_ACCESS.getLongUnaligned(session(), hb, byteOffset(nextGetIndex(8)), bigEndian);
}
public long getLong(int i) {
return SCOPED_MEMORY_ACCESS.getLongUnaligned(scope(), hb, byteOffset(checkIndex(i, 8)), bigEndian);
return SCOPED_MEMORY_ACCESS.getLongUnaligned(session(), hb, byteOffset(checkIndex(i, 8)), bigEndian);
}
#end[rw]
public $Type$Buffer putLong(long x) {
#if[rw]
SCOPED_MEMORY_ACCESS.putLongUnaligned(scope(), hb, byteOffset(nextPutIndex(8)), x, bigEndian);
SCOPED_MEMORY_ACCESS.putLongUnaligned(session(), hb, byteOffset(nextPutIndex(8)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -511,7 +511,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putLong(int i, long x) {
#if[rw]
SCOPED_MEMORY_ACCESS.putLongUnaligned(scope(), hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
SCOPED_MEMORY_ACCESS.putLongUnaligned(session(), hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -543,12 +543,12 @@ class Heap$Type$Buffer$RW$
#if[rw]
public float getFloat() {
int x = SCOPED_MEMORY_ACCESS.getIntUnaligned(scope(), hb, byteOffset(nextGetIndex(4)), bigEndian);
int x = SCOPED_MEMORY_ACCESS.getIntUnaligned(session(), hb, byteOffset(nextGetIndex(4)), bigEndian);
return Float.intBitsToFloat(x);
}
public float getFloat(int i) {
int x = SCOPED_MEMORY_ACCESS.getIntUnaligned(scope(), hb, byteOffset(checkIndex(i, 4)), bigEndian);
int x = SCOPED_MEMORY_ACCESS.getIntUnaligned(session(), hb, byteOffset(checkIndex(i, 4)), bigEndian);
return Float.intBitsToFloat(x);
}
@ -557,7 +557,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putFloat(float x) {
#if[rw]
int y = Float.floatToRawIntBits(x);
SCOPED_MEMORY_ACCESS.putIntUnaligned(scope(), hb, byteOffset(nextPutIndex(4)), y, bigEndian);
SCOPED_MEMORY_ACCESS.putIntUnaligned(session(), hb, byteOffset(nextPutIndex(4)), y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -567,7 +567,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putFloat(int i, float x) {
#if[rw]
int y = Float.floatToRawIntBits(x);
SCOPED_MEMORY_ACCESS.putIntUnaligned(scope(), hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
SCOPED_MEMORY_ACCESS.putIntUnaligned(session(), hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -599,12 +599,12 @@ class Heap$Type$Buffer$RW$
#if[rw]
public double getDouble() {
long x = SCOPED_MEMORY_ACCESS.getLongUnaligned(scope(), hb, byteOffset(nextGetIndex(8)), bigEndian);
long x = SCOPED_MEMORY_ACCESS.getLongUnaligned(session(), hb, byteOffset(nextGetIndex(8)), bigEndian);
return Double.longBitsToDouble(x);
}
public double getDouble(int i) {
long x = SCOPED_MEMORY_ACCESS.getLongUnaligned(scope(), hb, byteOffset(checkIndex(i, 8)), bigEndian);
long x = SCOPED_MEMORY_ACCESS.getLongUnaligned(session(), hb, byteOffset(checkIndex(i, 8)), bigEndian);
return Double.longBitsToDouble(x);
}
@ -613,7 +613,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putDouble(double x) {
#if[rw]
long y = Double.doubleToRawLongBits(x);
SCOPED_MEMORY_ACCESS.putLongUnaligned(scope(), hb, byteOffset(nextPutIndex(8)), y, bigEndian);
SCOPED_MEMORY_ACCESS.putLongUnaligned(session(), hb, byteOffset(nextPutIndex(8)), y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -623,7 +623,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putDouble(int i, double x) {
#if[rw]
long y = Double.doubleToRawLongBits(x);
SCOPED_MEMORY_ACCESS.putLongUnaligned(scope(), hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
SCOPED_MEMORY_ACCESS.putLongUnaligned(session(), hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2022, 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
@ -27,10 +27,10 @@ package java.nio;
import java.io.FileDescriptor;
import java.io.UncheckedIOException;
import java.lang.foreign.MemorySegment;
import java.lang.ref.Reference;
import java.util.Objects;
import jdk.internal.access.foreign.MemorySegmentProxy;
import jdk.internal.access.foreign.UnmapperProxy;
import jdk.internal.misc.ScopedMemoryAccess;
import jdk.internal.misc.Unsafe;
@ -96,20 +96,20 @@ public abstract sealed class MappedByteBuffer
// This should only be invoked by the DirectByteBuffer constructors
//
MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
FileDescriptor fd, boolean isSync, MemorySegmentProxy segment) {
FileDescriptor fd, boolean isSync, MemorySegment segment) {
super(mark, pos, lim, cap, segment);
this.fd = fd;
this.isSync = isSync;
}
MappedByteBuffer(int mark, int pos, int lim, int cap, // package-private
boolean isSync, MemorySegmentProxy segment) {
boolean isSync, MemorySegment segment) {
super(mark, pos, lim, cap, segment);
this.fd = null;
this.isSync = isSync;
}
MappedByteBuffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) { // package-private
MappedByteBuffer(int mark, int pos, int lim, int cap, MemorySegment segment) { // package-private
super(mark, pos, lim, cap, segment);
this.fd = null;
this.isSync = false;
@ -189,7 +189,7 @@ public abstract sealed class MappedByteBuffer
if (fd == null) {
return true;
}
return SCOPED_MEMORY_ACCESS.isLoaded(scope(), address, isSync, capacity());
return SCOPED_MEMORY_ACCESS.isLoaded(session(), address, isSync, capacity());
}
/**
@ -207,7 +207,7 @@ public abstract sealed class MappedByteBuffer
return this;
}
try {
SCOPED_MEMORY_ACCESS.load(scope(), address, isSync, capacity());
SCOPED_MEMORY_ACCESS.load(session(), address, isSync, capacity());
} finally {
Reference.reachabilityFence(this);
}
@ -307,7 +307,7 @@ public abstract sealed class MappedByteBuffer
if ((address != 0) && (capacity != 0)) {
// check inputs
Objects.checkFromIndexSize(index, length, capacity);
SCOPED_MEMORY_ACCESS.force(scope(), fd, address, isSync, index, length);
SCOPED_MEMORY_ACCESS.force(session(), fd, address, isSync, index, length);
}
return this;
}

View file

@ -37,8 +37,8 @@ import java.util.stream.StreamSupport;
import java.util.stream.$Streamtype$Stream;
#end[streamableType]
import java.lang.foreign.MemorySegment;
import java.util.Objects;
import jdk.internal.access.foreign.MemorySegmentProxy;
import jdk.internal.util.ArraysSupport;
/**
@ -293,7 +293,7 @@ public abstract sealed class $Type$Buffer
// backing array, and array offset
//
$Type$Buffer(int mark, int pos, int lim, int cap, // package-private
$type$[] hb, int offset, MemorySegmentProxy segment)
$type$[] hb, int offset, MemorySegment segment)
{
super(mark, pos, lim, cap, segment);
this.hb = hb;
@ -302,13 +302,13 @@ public abstract sealed class $Type$Buffer
// Creates a new buffer with the given mark, position, limit, and capacity
//
$Type$Buffer(int mark, int pos, int lim, int cap, MemorySegmentProxy segment) { // package-private
$Type$Buffer(int mark, int pos, int lim, int cap, MemorySegment segment) { // package-private
this(mark, pos, lim, cap, null, 0, segment);
}
// Creates a new buffer with given base, address and capacity
//
$Type$Buffer($type$[] hb, long addr, int cap, MemorySegmentProxy segment) { // package-private
$Type$Buffer($type$[] hb, long addr, int cap, MemorySegment segment) { // package-private
super(addr, cap, segment);
this.hb = hb;
this.offset = 0;
@ -935,12 +935,12 @@ public abstract sealed class $Type$Buffer
#if[!byte]
if (order() != ByteOrder.nativeOrder())
SCOPED_MEMORY_ACCESS.copySwapMemory(
scope(), null, base(), bufAddr,
session(), null, base(), bufAddr,
dst, dstOffset, len, $Fulltype$.BYTES);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(
scope(), null, base(), bufAddr,
session(), null, base(), bufAddr,
dst, dstOffset, len);
} finally {
Reference.reachabilityFence(this);
@ -1105,12 +1105,12 @@ public abstract sealed class $Type$Buffer
#if[!byte]
if (this.order() != src.order())
SCOPED_MEMORY_ACCESS.copySwapMemory(
src.scope(), scope(), srcBase, srcAddr,
src.session(), session(), srcBase, srcAddr,
base, addr, len, $Fulltype$.BYTES);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(
src.scope(), scope(), srcBase, srcAddr,
src.session(), session(), srcBase, srcAddr,
base, addr, len);
} finally {
Reference.reachabilityFence(src);
@ -1325,12 +1325,12 @@ public abstract sealed class $Type$Buffer
#if[!byte]
if (order() != ByteOrder.nativeOrder())
SCOPED_MEMORY_ACCESS.copySwapMemory(
null, scope(), src, srcOffset,
null, session(), src, srcOffset,
base(), bufAddr, len, $Fulltype$.BYTES);
else
#end[!byte]
SCOPED_MEMORY_ACCESS.copyMemory(
null, scope(), src, srcOffset,
null, session(), src, srcOffset,
base(), bufAddr, len);
} finally {
Reference.reachabilityFence(this);

View file

@ -26,6 +26,8 @@
package java.nio.channels;
import java.io.IOException;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySession;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.spi.AbstractInterruptibleChannel;
@ -38,6 +40,7 @@ import java.nio.file.spi.FileSystemProvider;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import jdk.internal.javac.PreviewFeature;
/**
* A channel for reading, writing, mapping, and manipulating a file.
@ -943,13 +946,13 @@ public abstract class FileChannel
*
* @throws NonReadableChannelException
* If the {@code mode} is {@link MapMode#READ_ONLY READ_ONLY} or
* an implementation specific map mode requiring read access
* an implementation specific map mode requiring read access,
* but this channel was not opened for reading
*
* @throws NonWritableChannelException
* If the {@code mode} is {@link MapMode#READ_WRITE READ_WRITE}.
* If the {@code mode} is {@link MapMode#READ_WRITE READ_WRITE},
* {@link MapMode#PRIVATE PRIVATE} or an implementation specific
* map mode requiring write access but this channel was not
* map mode requiring write access, but this channel was not
* opened for both reading and writing
*
* @throws IllegalArgumentException
@ -967,6 +970,89 @@ public abstract class FileChannel
public abstract MappedByteBuffer map(MapMode mode, long position, long size)
throws IOException;
/**
* Maps a region of this channel's file into a new mapped memory segment,
* with the given offset, size and memory session.
*
* <p> If the specified mapping mode is
* {@linkplain FileChannel.MapMode#READ_ONLY READ_ONLY}, the resulting
* segment will be read-only (see {@link MemorySegment#isReadOnly()}).
*
* <p> The content of a mapped memory segment can change at any time, for
* example if the content of the corresponding region of the mapped file is
* changed by this (or another) program. Whether such changes occur, and
* when they occur, is operating-system dependent and therefore unspecified.
*
* <p> All or part of a mapped memory segment may become inaccessible at any
* time, for example if the backing mapped file is truncated. An attempt to
* access an inaccessible region of a mapped memory segment will not change
* the segment's content and will cause an unspecified exception to be
* thrown either at the time of the access or at some later time. It is
* therefore strongly recommended that appropriate precautions be taken to
* avoid the manipulation of a mapped file by this (or another) program,
* except to read or write the file's content.
*
* @implNote When obtaining a mapped segment from a newly created file
* channel, 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.
*
* @param mode
* The file mapping mode, see
* {@link FileChannel#map(FileChannel.MapMode, long, long)};
* the mapping mode might affect the behavior of the returned memory
* mapped segment (see {@link MemorySegment#force()}).
*
* @param offset
* The offset (expressed in bytes) within the file at which the
* mapped segment is to start.
*
* @param size
* The size (in bytes) of the mapped memory backing the memory
* segment.
* @param session
* The segment memory session.
*
* @return A new mapped memory segment.
*
* @throws IllegalArgumentException
* If {@code offset < 0}, {@code size < 0} or
* {@code offset + size} overflows the range of {@code long}.
*
* @throws IllegalStateException
* If the {@code session} is not
* {@linkplain MemorySession#isAlive() alive}, or if access occurs
* from a thread other than the thread
* {@linkplain MemorySession#ownerThread() owning} the
* {@code session}.
*
* @throws NonReadableChannelException
* If the {@code mode} is {@link MapMode#READ_ONLY READ_ONLY} or
* an implementation specific map mode requiring read access,
* but this channel was not opened for reading.
*
* @throws NonWritableChannelException
* If the {@code mode} is {@link MapMode#READ_WRITE READ_WRITE},
* {@link MapMode#PRIVATE PRIVATE} or an implementation specific
* map mode requiring write access, but this channel was not
* opened for both reading and writing.
*
* @throws IOException
* If some other I/O error occurs.
*
* @throws UnsupportedOperationException
* If an unsupported map mode is specified.
*
* @since 19
*/
@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
public MemorySegment map(MapMode mode, long offset, long size,
MemorySession session)
throws IOException
{
throw new UnsupportedOperationException();
}
// -- Locks --