8287809: Revisit implementation of memory session

Reviewed-by: jvernee
This commit is contained in:
Maurizio Cimadamore 2022-07-11 14:30:19 +00:00
parent cb6e9cb728
commit fed3af8ae0
21 changed files with 328 additions and 383 deletions

View file

@ -37,7 +37,6 @@ import jdk.internal.vm.annotation.ForceInline;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.lang.foreign.MemorySegment; import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySession;
import java.util.Objects; import java.util.Objects;
import java.util.Spliterator; import java.util.Spliterator;
@ -771,11 +770,7 @@ public abstract sealed class Buffer
final void checkSession() { final void checkSession() {
MemorySessionImpl session = session(); MemorySessionImpl session = session();
if (session != null) { if (session != null) {
try {
session.checkValidState(); session.checkValidState();
} catch (ScopedMemoryAccess.ScopedAccessError e) {
throw new IllegalStateException("This segment is already closed");
}
} }
} }

View file

@ -313,11 +313,7 @@ class Direct$Type$Buffer$RW$$BO$
if (session.ownerThread() == null && session.isCloseable()) { if (session.ownerThread() == null && session.isCloseable()) {
throw new UnsupportedOperationException("ByteBuffer derived from closeable shared sessions not supported"); throw new UnsupportedOperationException("ByteBuffer derived from closeable shared sessions not supported");
} }
try {
session.checkValidState(); session.checkValidState();
} catch (ScopedAccessError e) {
throw new IllegalStateException("This segment is already closed");
}
} }
return address; return address;
} }

View file

@ -70,40 +70,33 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
static final int READ_ONLY = 1;
static final long NONCE = new Random().nextLong(); static final long NONCE = new Random().nextLong();
static final int DEFAULT_MODES = 0;
static final JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess(); static final JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();
final long length; final long length;
final int mask; final boolean readOnly;
final MemorySession session; final MemorySession session;
@ForceInline @ForceInline
AbstractMemorySegmentImpl(long length, int mask, MemorySession session) { AbstractMemorySegmentImpl(long length, boolean readOnly, MemorySession session) {
this.length = length; this.length = length;
this.mask = mask; this.readOnly = readOnly;
this.session = session; this.session = session;
} }
abstract long min(); abstract AbstractMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session);
abstract Object base();
abstract AbstractMemorySegmentImpl dup(long offset, long size, int mask, MemorySession session);
abstract ByteBuffer makeByteBuffer(); abstract ByteBuffer makeByteBuffer();
@Override @Override
public AbstractMemorySegmentImpl asReadOnly() { public AbstractMemorySegmentImpl asReadOnly() {
return dup(0, length, mask | READ_ONLY, session); return dup(0, length, true, session);
} }
@Override @Override
public boolean isReadOnly() { public boolean isReadOnly() {
return isSet(READ_ONLY); return readOnly;
} }
@Override @Override
@ -119,7 +112,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
} }
private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) { private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) {
return dup(offset, newSize, mask, session); return dup(offset, newSize, readOnly, session);
} }
@Override @Override
@ -147,7 +140,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
@Override @Override
public final MemorySegment fill(byte value){ public final MemorySegment fill(byte value){
checkAccess(0, length, false); checkAccess(0, length, false);
SCOPED_MEMORY_ACCESS.setMemory(sessionImpl(), base(), min(), length, value); SCOPED_MEMORY_ACCESS.setMemory(sessionImpl(), unsafeGetBase(), unsafeGetOffset(), length, value);
return this; return this;
} }
@ -176,8 +169,8 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
return 0; return 0;
} }
i = vectorizedMismatchLargeForBytes(sessionImpl(), that.sessionImpl(), i = vectorizedMismatchLargeForBytes(sessionImpl(), that.sessionImpl(),
this.base(), this.min(), this.unsafeGetBase(), this.unsafeGetOffset(),
that.base(), that.min(), that.unsafeGetBase(), that.unsafeGetOffset(),
length); length);
if (i >= 0) { if (i >= 0) {
return i; return i;
@ -235,7 +228,7 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
public final ByteBuffer asByteBuffer() { public final ByteBuffer asByteBuffer() {
checkArraySize("ByteBuffer", 1); checkArraySize("ByteBuffer", 1);
ByteBuffer _bb = makeByteBuffer(); ByteBuffer _bb = makeByteBuffer();
if (isSet(READ_ONLY)) { if (readOnly) {
//session is IMMUTABLE - obtain a RO byte buffer //session is IMMUTABLE - obtain a RO byte buffer
_bb = _bb.asReadOnlyBuffer(); _bb = _bb.asReadOnlyBuffer();
} }
@ -260,9 +253,9 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
@Override @Override
public final Optional<MemorySegment> asOverlappingSlice(MemorySegment other) { public final Optional<MemorySegment> asOverlappingSlice(MemorySegment other) {
AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other); AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other);
if (base() == that.base()) { // both either native or heap if (unsafeGetBase() == that.unsafeGetBase()) { // both either native or heap
final long thisStart = this.min(); final long thisStart = this.unsafeGetOffset();
final long thatStart = that.min(); final long thatStart = that.unsafeGetOffset();
final long thisEnd = thisStart + this.byteSize(); final long thisEnd = thisStart + this.byteSize();
final long thatEnd = thatStart + that.byteSize(); final long thatEnd = thatStart + that.byteSize();
@ -278,8 +271,8 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
@Override @Override
public final long segmentOffset(MemorySegment other) { public final long segmentOffset(MemorySegment other) {
AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl) Objects.requireNonNull(other); AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl) Objects.requireNonNull(other);
if (base() == that.base()) { if (unsafeGetBase() == that.unsafeGetBase()) {
return that.min() - this.min(); return that.unsafeGetOffset() - this.unsafeGetOffset();
} }
throw new UnsupportedOperationException("Cannot compute offset from native to heap (or vice versa)."); throw new UnsupportedOperationException("Cannot compute offset from native to heap (or vice versa).");
} }
@ -347,31 +340,24 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
return arr; return arr;
} }
@ForceInline
public void checkAccess(long offset, long length, boolean readOnly) { public void checkAccess(long offset, long length, boolean readOnly) {
if (!readOnly && isSet(READ_ONLY)) { if (!readOnly && this.readOnly) {
throw new UnsupportedOperationException("Attempt to write a read-only segment"); throw new UnsupportedOperationException("Attempt to write a read-only segment");
} }
checkBounds(offset, length); checkBounds(offset, length);
} }
public void checkValidState() { public void checkValidState() {
sessionImpl().checkValidStateSlow(); sessionImpl().checkValidState();
} }
public long unsafeGetOffset() { public abstract long unsafeGetOffset();
return min();
}
public Object unsafeGetBase() { public abstract Object unsafeGetBase();
return base();
}
// Helper methods // Helper methods
private boolean isSet(int mask) {
return (this.mask & mask) != 0;
}
public abstract long maxAlignMask(); public abstract long maxAlignMask();
@ForceInline @ForceInline
@ -407,25 +393,19 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
return outOfBoundException(offset, length); return outOfBoundException(offset, length);
} }
@Override
@ForceInline
public MemorySessionImpl sessionImpl() {
return MemorySessionImpl.toSessionImpl(session);
}
@Override @Override
public MemorySession session() { public MemorySession session() {
return session; return session;
} }
private IndexOutOfBoundsException outOfBoundException(long offset, long length) { private IndexOutOfBoundsException outOfBoundException(long offset, long length) {
return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; offset = %d; length = %d", return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; new offset = %d; new length = %d",
this, offset, length)); this, offset, length));
} }
protected int id() { protected int id() {
//compute a stable and random id for this memory segment //compute a stable and random id for this memory segment
return Math.abs(Objects.hash(base(), min(), NONCE)); return Math.abs(Objects.hash(unsafeGetBase(), unsafeGetOffset(), NONCE));
} }
static class SegmentSplitter implements Spliterator<MemorySegment> { static class SegmentSplitter implements Spliterator<MemorySegment> {
@ -541,42 +521,37 @@ public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegm
int size = limit - pos; int size = limit - pos;
AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl)nioAccess.bufferSegment(bb); AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl)nioAccess.bufferSegment(bb);
final MemorySessionImpl bufferSession; final MemorySession bufferSession;
int modes;
if (bufferSegment != null) { if (bufferSegment != null) {
bufferSession = bufferSegment.sessionImpl(); bufferSession = bufferSegment.session;
modes = bufferSegment.mask;
} else { } else {
bufferSession = MemorySessionImpl.heapSession(bb); bufferSession = MemorySessionImpl.heapSession(bb);
modes = DEFAULT_MODES;
}
if (bb.isReadOnly()) {
modes |= READ_ONLY;
} }
boolean readOnly = bb.isReadOnly();
int scaleFactor = getScaleFactor(bb); int scaleFactor = getScaleFactor(bb);
if (base != null) { if (base != null) {
if (base instanceof byte[]) { if (base instanceof byte[]) {
return new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes); return new HeapMemorySegmentImpl.OfByte(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
} else if (base instanceof short[]) { } else if (base instanceof short[]) {
return new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes); return new HeapMemorySegmentImpl.OfShort(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
} else if (base instanceof char[]) { } else if (base instanceof char[]) {
return new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes); return new HeapMemorySegmentImpl.OfChar(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
} else if (base instanceof int[]) { } else if (base instanceof int[]) {
return new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes); return new HeapMemorySegmentImpl.OfInt(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
} else if (base instanceof float[]) { } else if (base instanceof float[]) {
return new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes); return new HeapMemorySegmentImpl.OfFloat(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
} else if (base instanceof long[]) { } else if (base instanceof long[]) {
return new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes); return new HeapMemorySegmentImpl.OfLong(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
} else if (base instanceof double[]) { } else if (base instanceof double[]) {
return new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, modes); return new HeapMemorySegmentImpl.OfDouble(bbAddress + (pos << scaleFactor), base, size << scaleFactor, readOnly);
} else { } else {
throw new AssertionError("Cannot get here"); throw new AssertionError("Cannot get here");
} }
} else if (unmapper == null) { } else if (unmapper == null) {
return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, modes, bufferSession); return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferSession);
} else { } else {
// we can ignore scale factor here, a mapped buffer is always a byte buffer, so scaleFactor == 0. // we can ignore scale factor here, a mapped buffer is always a byte buffer, so scaleFactor == 0.
return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, modes, bufferSession); return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, readOnly, bufferSession);
} }
} }

View file

@ -55,17 +55,12 @@ final class ConfinedSession extends MemorySessionImpl {
super(owner, new ConfinedResourceList(), cleaner); super(owner, new ConfinedResourceList(), cleaner);
} }
@Override
public boolean isAlive() {
return state != CLOSED;
}
@Override @Override
@ForceInline @ForceInline
public void acquire0() { public void acquire0() {
checkValidStateSlow(); checkValidState();
if (state == MAX_FORKS) { if (state == MAX_FORKS) {
throw new IllegalStateException("Session keep alive limit exceeded"); throw tooManyAcquires();
} }
state++; state++;
} }
@ -85,11 +80,11 @@ final class ConfinedSession extends MemorySessionImpl {
} }
void justClose() { void justClose() {
checkValidStateSlow(); checkValidState();
if (state == 0 || state - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) { if (state == 0 || state - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) {
state = CLOSED; state = CLOSED;
} else { } else {
throw new IllegalStateException("Session is acquired by " + state + " clients"); throw alreadyAcquired(state);
} }
} }
@ -103,7 +98,7 @@ final class ConfinedSession extends MemorySessionImpl {
cleanup.next = fst; cleanup.next = fst;
fst = cleanup; fst = cleanup;
} else { } else {
throw new IllegalStateException("Already closed!"); throw alreadyClosed();
} }
} }
@ -114,7 +109,7 @@ final class ConfinedSession extends MemorySessionImpl {
fst = ResourceCleanup.CLOSED_LIST; fst = ResourceCleanup.CLOSED_LIST;
cleanup(prev); cleanup(prev);
} else { } else {
throw new IllegalStateException("Attempt to cleanup an already closed resource list"); throw alreadyClosed();
} }
} }
} }

View file

@ -40,7 +40,7 @@ import jdk.internal.vm.annotation.ForceInline;
* a base object (typically an array). To enhance performances, the access to the base object needs to feature * a base object (typically an array). To enhance performances, the access to the base object needs to feature
* sharp type information, as well as sharp null-check information. For this reason, many concrete subclasses * sharp type information, as well as sharp null-check information. For this reason, many concrete subclasses
* of {@link HeapMemorySegmentImpl} are defined (e.g. {@link OfFloat}, so that each subclass can override the * of {@link HeapMemorySegmentImpl} are defined (e.g. {@link OfFloat}, so that each subclass can override the
* {@link HeapMemorySegmentImpl#base()} method so that it returns an array of the correct (sharp) type. Note that * {@link HeapMemorySegmentImpl#unsafeGetBase()} method so that it returns an array of the correct (sharp) type. Note that
* the field type storing the 'base' coordinate is just Object; similarly, all the constructor in the subclasses * the field type storing the 'base' coordinate is just Object; similarly, all the constructor in the subclasses
* accept an Object 'base' parameter instead of a sharper type (e.g. {@code byte[]}). This is deliberate, as * accept an Object 'base' parameter instead of a sharper type (e.g. {@code byte[]}). This is deliberate, as
* using sharper types would require use of type-conversions, which in turn would inhibit some C2 optimizations, * using sharper types would require use of type-conversions, which in turn would inhibit some C2 optimizations,
@ -60,54 +60,51 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
final Object base; final Object base;
@ForceInline @ForceInline
HeapMemorySegmentImpl(long offset, Object base, long length, int mask) { HeapMemorySegmentImpl(long offset, Object base, long length, boolean readOnly) {
super(length, mask, MemorySessionImpl.GLOBAL); super(length, readOnly, MemorySessionImpl.GLOBAL);
this.offset = offset; this.offset = offset;
this.base = base; this.base = base;
} }
@Override @Override
abstract Object base(); public long unsafeGetOffset() {
@Override
long min() {
return offset; return offset;
} }
@Override @Override
abstract HeapMemorySegmentImpl dup(long offset, long size, int mask, MemorySession session); abstract HeapMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session);
@Override @Override
ByteBuffer makeByteBuffer() { ByteBuffer makeByteBuffer() {
if (!(base() instanceof byte[])) { if (!(base instanceof byte[])) {
throw new UnsupportedOperationException("Not an address to an heap-allocated byte array"); throw new UnsupportedOperationException("Not an address to an heap-allocated byte array");
} }
JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess(); JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess();
return nioAccess.newHeapByteBuffer((byte[]) base(), (int)min() - BYTE_ARR_BASE, (int) byteSize(), null); return nioAccess.newHeapByteBuffer((byte[])base, (int)offset - BYTE_ARR_BASE, (int) byteSize(), null);
} }
// factories // factories
public static class OfByte extends HeapMemorySegmentImpl { public static class OfByte extends HeapMemorySegmentImpl {
OfByte(long offset, Object base, long length, int mask) { OfByte(long offset, Object base, long length, boolean readOnly) {
super(offset, base, length, mask); super(offset, base, length, readOnly);
} }
@Override @Override
OfByte dup(long offset, long size, int mask, MemorySession session) { OfByte dup(long offset, long size, boolean readOnly, MemorySession session) {
return new OfByte(this.offset + offset, base, size, mask); return new OfByte(this.offset + offset, base, size, readOnly);
} }
@Override @Override
byte[] base() { public byte[] unsafeGetBase() {
return (byte[])Objects.requireNonNull(base); return (byte[])Objects.requireNonNull(base);
} }
public static MemorySegment fromArray(byte[] arr) { public static MemorySegment fromArray(byte[] arr) {
Objects.requireNonNull(arr); Objects.requireNonNull(arr);
long byteSize = (long)arr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE; long byteSize = (long)arr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE;
return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, DEFAULT_MODES); return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, false);
} }
@Override @Override
@ -118,24 +115,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
public static class OfChar extends HeapMemorySegmentImpl { public static class OfChar extends HeapMemorySegmentImpl {
OfChar(long offset, Object base, long length, int mask) { OfChar(long offset, Object base, long length, boolean readOnly) {
super(offset, base, length, mask); super(offset, base, length, readOnly);
} }
@Override @Override
OfChar dup(long offset, long size, int mask, MemorySession session) { OfChar dup(long offset, long size, boolean readOnly, MemorySession session) {
return new OfChar(this.offset + offset, base, size, mask); return new OfChar(this.offset + offset, base, size, readOnly);
} }
@Override @Override
char[] base() { public char[] unsafeGetBase() {
return (char[])Objects.requireNonNull(base); return (char[])Objects.requireNonNull(base);
} }
public static MemorySegment fromArray(char[] arr) { public static MemorySegment fromArray(char[] arr) {
Objects.requireNonNull(arr); Objects.requireNonNull(arr);
long byteSize = (long)arr.length * Unsafe.ARRAY_CHAR_INDEX_SCALE; long byteSize = (long)arr.length * Unsafe.ARRAY_CHAR_INDEX_SCALE;
return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, DEFAULT_MODES); return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, false);
} }
@Override @Override
@ -146,24 +143,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
public static class OfShort extends HeapMemorySegmentImpl { public static class OfShort extends HeapMemorySegmentImpl {
OfShort(long offset, Object base, long length, int mask) { OfShort(long offset, Object base, long length, boolean readOnly) {
super(offset, base, length, mask); super(offset, base, length, readOnly);
} }
@Override @Override
OfShort dup(long offset, long size, int mask, MemorySession session) { OfShort dup(long offset, long size, boolean readOnly, MemorySession session) {
return new OfShort(this.offset + offset, base, size, mask); return new OfShort(this.offset + offset, base, size, readOnly);
} }
@Override @Override
short[] base() { public short[] unsafeGetBase() {
return (short[])Objects.requireNonNull(base); return (short[])Objects.requireNonNull(base);
} }
public static MemorySegment fromArray(short[] arr) { public static MemorySegment fromArray(short[] arr) {
Objects.requireNonNull(arr); Objects.requireNonNull(arr);
long byteSize = (long)arr.length * Unsafe.ARRAY_SHORT_INDEX_SCALE; long byteSize = (long)arr.length * Unsafe.ARRAY_SHORT_INDEX_SCALE;
return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, DEFAULT_MODES); return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, false);
} }
@Override @Override
@ -174,24 +171,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
public static class OfInt extends HeapMemorySegmentImpl { public static class OfInt extends HeapMemorySegmentImpl {
OfInt(long offset, Object base, long length, int mask) { OfInt(long offset, Object base, long length, boolean readOnly) {
super(offset, base, length, mask); super(offset, base, length, readOnly);
} }
@Override @Override
OfInt dup(long offset, long size, int mask, MemorySession session) { OfInt dup(long offset, long size, boolean readOnly, MemorySession session) {
return new OfInt(this.offset + offset, base, size, mask); return new OfInt(this.offset + offset, base, size, readOnly);
} }
@Override @Override
int[] base() { public int[] unsafeGetBase() {
return (int[])Objects.requireNonNull(base); return (int[])Objects.requireNonNull(base);
} }
public static MemorySegment fromArray(int[] arr) { public static MemorySegment fromArray(int[] arr) {
Objects.requireNonNull(arr); Objects.requireNonNull(arr);
long byteSize = (long)arr.length * Unsafe.ARRAY_INT_INDEX_SCALE; long byteSize = (long)arr.length * Unsafe.ARRAY_INT_INDEX_SCALE;
return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, DEFAULT_MODES); return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, false);
} }
@Override @Override
@ -202,24 +199,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
public static class OfLong extends HeapMemorySegmentImpl { public static class OfLong extends HeapMemorySegmentImpl {
OfLong(long offset, Object base, long length, int mask) { OfLong(long offset, Object base, long length, boolean readOnly) {
super(offset, base, length, mask); super(offset, base, length, readOnly);
} }
@Override @Override
OfLong dup(long offset, long size, int mask, MemorySession session) { OfLong dup(long offset, long size, boolean readOnly, MemorySession session) {
return new OfLong(this.offset + offset, base, size, mask); return new OfLong(this.offset + offset, base, size, readOnly);
} }
@Override @Override
long[] base() { public long[] unsafeGetBase() {
return (long[])Objects.requireNonNull(base); return (long[])Objects.requireNonNull(base);
} }
public static MemorySegment fromArray(long[] arr) { public static MemorySegment fromArray(long[] arr) {
Objects.requireNonNull(arr); Objects.requireNonNull(arr);
long byteSize = (long)arr.length * Unsafe.ARRAY_LONG_INDEX_SCALE; long byteSize = (long)arr.length * Unsafe.ARRAY_LONG_INDEX_SCALE;
return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, DEFAULT_MODES); return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, false);
} }
@Override @Override
@ -230,24 +227,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
public static class OfFloat extends HeapMemorySegmentImpl { public static class OfFloat extends HeapMemorySegmentImpl {
OfFloat(long offset, Object base, long length, int mask) { OfFloat(long offset, Object base, long length, boolean readOnly) {
super(offset, base, length, mask); super(offset, base, length, readOnly);
} }
@Override @Override
OfFloat dup(long offset, long size, int mask, MemorySession session) { OfFloat dup(long offset, long size, boolean readOnly, MemorySession session) {
return new OfFloat(this.offset + offset, base, size, mask); return new OfFloat(this.offset + offset, base, size, readOnly);
} }
@Override @Override
float[] base() { public float[] unsafeGetBase() {
return (float[])Objects.requireNonNull(base); return (float[])Objects.requireNonNull(base);
} }
public static MemorySegment fromArray(float[] arr) { public static MemorySegment fromArray(float[] arr) {
Objects.requireNonNull(arr); Objects.requireNonNull(arr);
long byteSize = (long)arr.length * Unsafe.ARRAY_FLOAT_INDEX_SCALE; long byteSize = (long)arr.length * Unsafe.ARRAY_FLOAT_INDEX_SCALE;
return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, DEFAULT_MODES); return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, false);
} }
@Override @Override
@ -258,24 +255,24 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl {
public static class OfDouble extends HeapMemorySegmentImpl { public static class OfDouble extends HeapMemorySegmentImpl {
OfDouble(long offset, Object base, long length, int mask) { OfDouble(long offset, Object base, long length, boolean readOnly) {
super(offset, base, length, mask); super(offset, base, length, readOnly);
} }
@Override @Override
OfDouble dup(long offset, long size, int mask, MemorySession session) { OfDouble dup(long offset, long size, boolean readOnly, MemorySession session) {
return new OfDouble(this.offset + offset, base, size, mask); return new OfDouble(this.offset + offset, base, size, readOnly);
} }
@Override @Override
double[] base() { public double[] unsafeGetBase() {
return (double[])Objects.requireNonNull(base); return (double[])Objects.requireNonNull(base);
} }
public static MemorySegment fromArray(double[] arr) { public static MemorySegment fromArray(double[] arr) {
Objects.requireNonNull(arr); Objects.requireNonNull(arr);
long byteSize = (long)arr.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE; long byteSize = (long)arr.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, DEFAULT_MODES); return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, false);
} }
@Override @Override

View file

@ -43,8 +43,8 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl {
static ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); static ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
public MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, int mask, MemorySession session) { public MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, boolean readOnly, MemorySession session) {
super(min, length, mask, session); super(min, length, readOnly, session);
this.unmapper = unmapper; this.unmapper = unmapper;
} }
@ -55,8 +55,8 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl {
} }
@Override @Override
MappedMemorySegmentImpl dup(long offset, long size, int mask, MemorySession session) { MappedMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) {
return new MappedMemorySegmentImpl(min + offset, unmapper, size, mask, session); return new MappedMemorySegmentImpl(min + offset, unmapper, size, readOnly, session);
} }
// mapped segment methods // mapped segment methods
@ -95,8 +95,8 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl {
public static class EmptyMappedMemorySegmentImpl extends MappedMemorySegmentImpl { public static class EmptyMappedMemorySegmentImpl extends MappedMemorySegmentImpl {
public EmptyMappedMemorySegmentImpl(int modes, MemorySession session) { public EmptyMappedMemorySegmentImpl(boolean readOnly, MemorySessionImpl session) {
super(0, null, 0, modes, session); super(0, null, 0, readOnly, session);
} }
@Override @Override

View file

@ -95,7 +95,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
} }
@Override @Override
public MemorySessionImpl sessionImpl() { public MemorySessionImpl session() {
return MemorySessionImpl.GLOBAL; return MemorySessionImpl.GLOBAL;
} }

View file

@ -43,16 +43,16 @@ import sun.nio.ch.DirectBuffer;
* This class manages the temporal bounds associated with a memory segment as well * This class manages the temporal bounds associated with a memory segment as well
* as thread confinement. A session has a liveness bit, which is updated when the session is closed * as thread confinement. A session has a liveness bit, which is updated when the session is closed
* (this operation is triggered by {@link MemorySession#close()}). This bit is consulted prior * (this operation is triggered by {@link MemorySession#close()}). This bit is consulted prior
* to memory access (see {@link #checkValidState()}). * to memory access (see {@link #checkValidStateRaw()}).
* There are two kinds of memory session: confined memory session and shared memory session. * There are two kinds of memory session: confined memory session and shared memory session.
* A confined memory session has an associated owner thread that confines some operations to * A confined memory session has an associated owner thread that confines some operations to
* associated owner thread such as {@link #close()} or {@link #checkValidState()}. * associated owner thread such as {@link #close()} or {@link #checkValidStateRaw()}.
* Shared sessions do not feature an owner thread - meaning their operations can be called, in a racy * Shared sessions do not feature an owner thread - meaning their operations can be called, in a racy
* manner, by multiple threads. To guarantee temporal safety in the presence of concurrent thread, * manner, by multiple threads. To guarantee temporal safety in the presence of concurrent thread,
* shared sessions use a more sophisticated synchronization mechanism, which guarantees that no concurrent * shared sessions use a more sophisticated synchronization mechanism, which guarantees that no concurrent
* access is possible when a session is being closed (see {@link jdk.internal.misc.ScopedMemoryAccess}). * access is possible when a session is being closed (see {@link jdk.internal.misc.ScopedMemoryAccess}).
*/ */
public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySession, SegmentAllocator { public abstract non-sealed class MemorySessionImpl implements MemorySession, SegmentAllocator {
final ResourceList resourceList; final ResourceList resourceList;
final Cleaner.Cleanable cleanable; final Cleaner.Cleanable cleanable;
final Thread owner; final Thread owner;
@ -78,8 +78,7 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
@Override @Override
public void addCloseAction(Runnable runnable) { public void addCloseAction(Runnable runnable) {
Objects.requireNonNull(runnable); Objects.requireNonNull(runnable);
addInternal(runnable instanceof ResourceList.ResourceCleanup cleanup ? addInternal(ResourceList.ResourceCleanup.ofRunnable(runnable));
cleanup : ResourceList.ResourceCleanup.ofRunnable(runnable));
} }
/** /**
@ -102,7 +101,7 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
} }
void addInternal(ResourceList.ResourceCleanup resource) { void addInternal(ResourceList.ResourceCleanup resource) {
checkValidStateSlow(); checkValidState();
// Note: from here on we no longer check the session state. Two cases are possible: either the resource cleanup // Note: from here on we no longer check the session state. Two cases are possible: either the resource cleanup
// is added to the list when the session is still open, in which case everything works ok; or the resource // is added to the list when the session is still open, in which case everything works ok; or the resource
// cleanup is added while the session is being closed. In this latter case, what matters is whether we have already // cleanup is added while the session is being closed. In this latter case, what matters is whether we have already
@ -141,13 +140,13 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
public abstract void acquire0(); public abstract void acquire0();
@Override @Override
public boolean equals(Object o) { public final boolean equals(Object o) {
return (o instanceof MemorySession other) && return (o instanceof MemorySession other) &&
toSessionImpl(other) == this; toSessionImpl(other) == this;
} }
@Override @Override
public int hashCode() { public final int hashCode() {
return super.hashCode(); return super.hashCode();
} }
@ -174,7 +173,9 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
* Returns true, if this session is still open. This method may be called in any thread. * Returns true, if this session is still open. This method may be called in any thread.
* @return {@code true} if this session is not closed yet. * @return {@code true} if this session is not closed yet.
*/ */
public abstract boolean isAlive(); public boolean isAlive() {
return state >= OPEN;
}
@Override @Override
public MemorySession asNonCloseable() { public MemorySession asNonCloseable() {
@ -182,30 +183,27 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
new NonCloseableView(this) : this; new NonCloseableView(this) : this;
} }
@ForceInline
public static MemorySessionImpl toSessionImpl(MemorySession session) { public static MemorySessionImpl toSessionImpl(MemorySession session) {
return ((Scoped)session).sessionImpl(); return session instanceof MemorySessionImpl sessionImpl ?
} sessionImpl : ((NonCloseableView)session).session;
@Override
public MemorySessionImpl sessionImpl() {
return this;
} }
/** /**
* This is a faster version of {@link #checkValidStateSlow()}, which is called upon memory access, and which * This is a faster version of {@link #checkValidState()}, which is called upon memory access, and which
* relies on invariants associated with the memory session implementations (volatile access * relies on invariants associated with the memory session implementations (volatile access
* to the closed state bit is replaced with plain access). This method should be monomorphic, * to the closed state bit is replaced with plain access). This method should be monomorphic,
* to avoid virtual calls in the memory access hot path. This method is not intended as general purpose method * to avoid virtual calls in the memory access hot path. This method is not intended as general purpose method
* and should only be used in the memory access handle hot path; for liveness checks triggered by other API methods, * and should only be used in the memory access handle hot path; for liveness checks triggered by other API methods,
* please use {@link #checkValidStateSlow()}. * please use {@link #checkValidState()}.
*/ */
@ForceInline @ForceInline
public final void checkValidState() { public void checkValidStateRaw() {
if (owner != null && owner != Thread.currentThread()) { if (owner != null && owner != Thread.currentThread()) {
throw new WrongThreadException("Attempted access outside owning thread"); throw WRONG_THREAD;
} }
if (state < OPEN) { if (state < OPEN) {
throw ScopedMemoryAccess.ScopedAccessError.INSTANCE; throw ALREADY_CLOSED;
} }
} }
@ -214,11 +212,11 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
* @throws IllegalStateException if this session is already closed or if this is * @throws IllegalStateException if this session is already closed or if this is
* a confined session and this method is called outside of the owner thread. * a confined session and this method is called outside of the owner thread.
*/ */
public final void checkValidStateSlow() { public void checkValidState() {
if (owner != null && Thread.currentThread() != owner) { try {
throw new WrongThreadException("Attempted access outside owning thread"); checkValidStateRaw();
} else if (!isAlive()) { } catch (ScopedMemoryAccess.ScopedAccessError error) {
throw new IllegalStateException("Already closed"); throw error.newRuntimeException();
} }
} }
@ -289,14 +287,9 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
// do nothing // do nothing
} }
@Override
public boolean isAlive() {
return true;
}
@Override @Override
public void justClose() { public void justClose() {
throw new UnsupportedOperationException(); throw nonCloseable();
} }
} }
@ -335,19 +328,9 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
return false; return false;
} }
@Override
public boolean isAlive() {
return true;
}
@Override
public MemorySession asNonCloseable() {
return this;
}
@Override @Override
public void justClose() { public void justClose() {
throw new UnsupportedOperationException(); throw nonCloseable();
} }
} }
@ -358,17 +341,13 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
* a strong reference to the original session, so even if the original session is dropped by the client * a strong reference to the original session, so even if the original session is dropped by the client
* it would still be reachable by the GC, which is important if the session is implicitly closed. * it would still be reachable by the GC, which is important if the session is implicitly closed.
*/ */
public final static class NonCloseableView implements MemorySession, Scoped { public final static class NonCloseableView implements MemorySession {
final MemorySessionImpl session; final MemorySessionImpl session;
public NonCloseableView(MemorySessionImpl session) { public NonCloseableView(MemorySessionImpl session) {
this.session = session; this.session = session;
} }
public MemorySessionImpl sessionImpl() {
return session;
}
@Override @Override
public boolean isAlive() { public boolean isAlive() {
return session.isAlive(); return session.isAlive();
@ -461,6 +440,31 @@ public abstract non-sealed class MemorySessionImpl implements Scoped, MemorySess
}; };
} }
} }
}
// helper functions to centralize error handling
static IllegalStateException tooManyAcquires() {
return new IllegalStateException("Session acquire limit exceeded");
} }
static IllegalStateException alreadyAcquired(int acquires) {
return new IllegalStateException(String.format("Session is acquired by %d clients", acquires));
}
static IllegalStateException alreadyClosed() {
return new IllegalStateException("Already closed");
}
static WrongThreadException wrongThread() {
return new WrongThreadException("Attempted access outside owning thread");
}
static UnsupportedOperationException nonCloseable() {
return new UnsupportedOperationException("Attempted to close a non-closeable session");
}
static final ScopedMemoryAccess.ScopedAccessError ALREADY_CLOSED = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::alreadyClosed);
static final ScopedMemoryAccess.ScopedAccessError WRONG_THREAD = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::wrongThread);
} }

View file

@ -41,14 +41,14 @@ import sun.security.action.GetBooleanAction;
*/ */
public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl { public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
public static final MemorySegment EVERYTHING = new NativeMemorySegmentImpl(0, Long.MAX_VALUE, 0, MemorySessionImpl.GLOBAL) { public static final MemorySegment EVERYTHING = new NativeMemorySegmentImpl(0, Long.MAX_VALUE, false, MemorySessionImpl.GLOBAL) {
@Override @Override
void checkBounds(long offset, long length) { void checkBounds(long offset, long length) {
// do nothing // do nothing
} }
@Override @Override
NativeMemorySegmentImpl dup(long offset, long size, int mask, MemorySession scope) { NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
}; };
@ -64,8 +64,8 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
final long min; final long min;
@ForceInline @ForceInline
NativeMemorySegmentImpl(long min, long length, int mask, MemorySession session) { NativeMemorySegmentImpl(long min, long length, boolean readOnly, MemorySession session) {
super(length, mask, session); super(length, readOnly, session);
this.min = min; this.min = min;
} }
@ -77,13 +77,13 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
} }
@Override @Override
NativeMemorySegmentImpl dup(long offset, long size, int mask, MemorySession session) { NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) {
return new NativeMemorySegmentImpl(min + offset, size, mask, session); return new NativeMemorySegmentImpl(min + offset, size, readOnly, session);
} }
@Override @Override
ByteBuffer makeByteBuffer() { ByteBuffer makeByteBuffer() {
return nioAccess.newDirectByteBuffer(min(), (int) this.length, null, return nioAccess.newDirectByteBuffer(min, (int) this.length, null,
session == MemorySessionImpl.GLOBAL ? null : this); session == MemorySessionImpl.GLOBAL ? null : this);
} }
@ -93,12 +93,12 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
} }
@Override @Override
long min() { public long unsafeGetOffset() {
return min; return min;
} }
@Override @Override
Object base() { public Object unsafeGetBase() {
return null; return null;
} }
@ -111,7 +111,7 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
public static MemorySegment makeNativeSegment(long bytesSize, long alignmentBytes, MemorySession session) { public static MemorySegment makeNativeSegment(long bytesSize, long alignmentBytes, MemorySession session) {
MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session); MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session);
sessionImpl.checkValidStateSlow(); sessionImpl.checkValidState();
if (VM.isDirectMemoryPageAligned()) { if (VM.isDirectMemoryPageAligned()) {
alignmentBytes = Math.max(alignmentBytes, nioAccess.pageSize()); alignmentBytes = Math.max(alignmentBytes, nioAccess.pageSize());
} }
@ -127,7 +127,7 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
} }
long alignedBuf = Utils.alignUp(buf, alignmentBytes); long alignedBuf = Utils.alignUp(buf, alignmentBytes);
AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(buf, alignedSize, AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(buf, alignedSize,
DEFAULT_MODES, session); false, session);
sessionImpl.addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { sessionImpl.addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() {
@Override @Override
public void cleanup() { public void cleanup() {
@ -143,9 +143,8 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
} }
public static MemorySegment makeNativeSegmentUnchecked(MemoryAddress min, long bytesSize, MemorySession session) { public static MemorySegment makeNativeSegmentUnchecked(MemoryAddress min, long bytesSize, MemorySession session) {
MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session); MemorySessionImpl.toSessionImpl(session).checkValidState();
sessionImpl.checkValidStateSlow(); AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(min.toRawLongValue(), bytesSize, false, session);
AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(min.toRawLongValue(), bytesSize, DEFAULT_MODES, session);
return segment; return segment;
} }
} }

View file

@ -25,6 +25,14 @@
package jdk.internal.foreign; package jdk.internal.foreign;
import jdk.internal.vm.annotation.ForceInline;
import java.lang.foreign.MemorySession;
public interface Scoped { public interface Scoped {
MemorySessionImpl sessionImpl(); @ForceInline
default MemorySessionImpl sessionImpl() {
return MemorySessionImpl.toSessionImpl(session());
}
MemorySession session();
} }

View file

@ -56,10 +56,10 @@ class SharedSession extends MemorySessionImpl {
value = (int) STATE.getVolatile(this); value = (int) STATE.getVolatile(this);
if (value < OPEN) { if (value < OPEN) {
//segment is not open! //segment is not open!
throw new IllegalStateException("Already closed"); throw alreadyClosed();
} else if (value == MAX_FORKS) { } else if (value == MAX_FORKS) {
//overflow //overflow
throw new IllegalStateException("Session acquire limit exceeded"); throw tooManyAcquires();
} }
} while (!STATE.compareAndSet(this, value, value + 1)); } while (!STATE.compareAndSet(this, value, value + 1));
} }
@ -72,7 +72,7 @@ class SharedSession extends MemorySessionImpl {
value = (int) STATE.getVolatile(this); value = (int) STATE.getVolatile(this);
if (value <= OPEN) { if (value <= OPEN) {
//cannot get here - we can't close segment twice //cannot get here - we can't close segment twice
throw new IllegalStateException("Already closed"); throw alreadyClosed();
} }
} while (!STATE.compareAndSet(this, value, value - 1)); } while (!STATE.compareAndSet(this, value, value - 1));
} }
@ -80,22 +80,17 @@ class SharedSession extends MemorySessionImpl {
void justClose() { void justClose() {
int prevState = (int) STATE.compareAndExchange(this, OPEN, CLOSING); int prevState = (int) STATE.compareAndExchange(this, OPEN, CLOSING);
if (prevState < 0) { if (prevState < 0) {
throw new IllegalStateException("Already closed"); throw alreadyClosed();
} else if (prevState != OPEN) { } else if (prevState != OPEN) {
throw new IllegalStateException("Session is acquired by " + prevState + " clients"); throw alreadyAcquired(prevState);
} }
boolean success = SCOPED_MEMORY_ACCESS.closeScope(this); boolean success = SCOPED_MEMORY_ACCESS.closeScope(this);
STATE.setVolatile(this, success ? CLOSED : OPEN); STATE.setVolatile(this, success ? CLOSED : OPEN);
if (!success) { if (!success) {
throw new IllegalStateException("Session is acquired by 1 client"); throw alreadyAcquired(1);
} }
} }
@Override
public boolean isAlive() {
return (int) STATE.getVolatile(this) != CLOSED;
}
/** /**
* A shared resource list; this implementation has to handle add vs. add races, as well as add vs. cleanup races. * A shared resource list; this implementation has to handle add vs. add races, as well as add vs. cleanup races.
*/ */
@ -117,7 +112,7 @@ class SharedSession extends MemorySessionImpl {
ResourceCleanup prev = (ResourceCleanup) FST.getVolatile(this); ResourceCleanup prev = (ResourceCleanup) FST.getVolatile(this);
if (prev == ResourceCleanup.CLOSED_LIST) { if (prev == ResourceCleanup.CLOSED_LIST) {
// too late // too late
throw new IllegalStateException("Already closed"); throw alreadyClosed();
} }
cleanup.next = prev; cleanup.next = prev;
if (FST.compareAndSet(this, prev, cleanup)) { if (FST.compareAndSet(this, prev, cleanup)) {
@ -144,7 +139,7 @@ class SharedSession extends MemorySessionImpl {
} }
cleanup(prev); cleanup(prev);
} else { } else {
throw new IllegalStateException("Attempt to cleanup an already closed resource list"); throw alreadyClosed();
} }
} }
} }

View file

@ -445,11 +445,6 @@ public class SharedUtils {
return MemorySessionImpl.GLOBAL; return MemorySessionImpl.GLOBAL;
} }
@Override
public MemorySessionImpl sessionImpl() {
return MemorySessionImpl.GLOBAL;
}
@Override @Override
public VaList copy() { public VaList copy() {
return this; return this;

View file

@ -320,7 +320,7 @@ public non-sealed class LinuxAArch64VaList implements VaList, Scoped {
@Override @Override
public void skip(MemoryLayout... layouts) { public void skip(MemoryLayout... layouts) {
Objects.requireNonNull(layouts); Objects.requireNonNull(layouts);
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow(); sessionImpl().checkValidState();
for (MemoryLayout layout : layouts) { for (MemoryLayout layout : layouts) {
Objects.requireNonNull(layout); Objects.requireNonNull(layout);
TypeClass typeClass = TypeClass.classifyLayout(layout); TypeClass typeClass = TypeClass.classifyLayout(layout);
@ -350,11 +350,6 @@ public non-sealed class LinuxAArch64VaList implements VaList, Scoped {
return segment.session(); return segment.session();
} }
@Override
public MemorySessionImpl sessionImpl() {
return MemorySessionImpl.toSessionImpl(session());
}
@Override @Override
public VaList copy() { public VaList copy() {
MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.session()); MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.session());

View file

@ -127,7 +127,7 @@ public non-sealed class MacOsAArch64VaList implements VaList, Scoped {
@Override @Override
public void skip(MemoryLayout... layouts) { public void skip(MemoryLayout... layouts) {
Objects.requireNonNull(layouts); Objects.requireNonNull(layouts);
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow(); sessionImpl().checkValidState();
for (MemoryLayout layout : layouts) { for (MemoryLayout layout : layouts) {
Objects.requireNonNull(layout); Objects.requireNonNull(layout);
@ -152,14 +152,9 @@ public non-sealed class MacOsAArch64VaList implements VaList, Scoped {
return session; return session;
} }
@Override
public MemorySessionImpl sessionImpl() {
return MemorySessionImpl.toSessionImpl(session());
}
@Override @Override
public VaList copy() { public VaList copy() {
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow(); sessionImpl().checkValidState();
return new MacOsAArch64VaList(segment, session); return new MacOsAArch64VaList(segment, session);
} }
@ -174,7 +169,7 @@ public non-sealed class MacOsAArch64VaList implements VaList, Scoped {
private final List<SimpleVaArg> args = new ArrayList<>(); private final List<SimpleVaArg> args = new ArrayList<>();
public Builder(MemorySession session) { public Builder(MemorySession session) {
MemorySessionImpl.toSessionImpl(session).checkValidStateSlow(); MemorySessionImpl.toSessionImpl(session).checkValidState();
this.session = session; this.session = session;
} }

View file

@ -277,7 +277,7 @@ public non-sealed class SysVVaList implements VaList, Scoped {
@Override @Override
public void skip(MemoryLayout... layouts) { public void skip(MemoryLayout... layouts) {
Objects.requireNonNull(layouts); Objects.requireNonNull(layouts);
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow(); sessionImpl().checkValidState();
for (MemoryLayout layout : layouts) { for (MemoryLayout layout : layouts) {
Objects.requireNonNull(layout); Objects.requireNonNull(layout);
TypeClass typeClass = TypeClass.classifyLayout(layout); TypeClass typeClass = TypeClass.classifyLayout(layout);
@ -304,11 +304,6 @@ public non-sealed class SysVVaList implements VaList, Scoped {
return segment.session(); return segment.session();
} }
@Override
public MemorySessionImpl sessionImpl() {
return MemorySessionImpl.toSessionImpl(session());
}
@Override @Override
public VaList copy() { public VaList copy() {
MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.session()); MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.session());

View file

@ -133,7 +133,7 @@ public non-sealed class WinVaList implements VaList, Scoped {
@Override @Override
public void skip(MemoryLayout... layouts) { public void skip(MemoryLayout... layouts) {
Objects.requireNonNull(layouts); Objects.requireNonNull(layouts);
MemorySessionImpl.toSessionImpl(session()).checkValidStateSlow(); sessionImpl().checkValidState();
Stream.of(layouts).forEach(Objects::requireNonNull); Stream.of(layouts).forEach(Objects::requireNonNull);
segment = segment.asSlice(layouts.length * VA_SLOT_SIZE_BYTES); segment = segment.asSlice(layouts.length * VA_SLOT_SIZE_BYTES);
} }
@ -152,14 +152,9 @@ public non-sealed class WinVaList implements VaList, Scoped {
return session; return session;
} }
@Override
public MemorySessionImpl sessionImpl() {
return MemorySessionImpl.toSessionImpl(session());
}
@Override @Override
public VaList copy() { public VaList copy() {
MemorySessionImpl.toSessionImpl(session).checkValidStateSlow(); sessionImpl().checkValidState();
return new WinVaList(segment, session); return new WinVaList(segment, session);
} }
@ -174,7 +169,7 @@ public non-sealed class WinVaList implements VaList, Scoped {
private final List<SimpleVaArg> args = new ArrayList<>(); private final List<SimpleVaArg> args = new ArrayList<>();
public Builder(MemorySession session) { public Builder(MemorySession session) {
MemorySessionImpl.toSessionImpl(session).checkValidStateSlow(); MemorySessionImpl.toSessionImpl(session).checkValidState();
this.session = session; this.session = session;
} }

View file

@ -3,7 +3,7 @@
try { try {
return get$Type$Internal(session, base, offset); return get$Type$Internal(session, base, offset);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -11,7 +11,7 @@
private $type$ get$Type$Internal(MemorySessionImpl session, Object base, long offset) { private $type$ get$Type$Internal(MemorySessionImpl session, Object base, long offset) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.get$Type$(base, offset); return UNSAFE.get$Type$(base, offset);
} finally { } finally {
@ -24,7 +24,7 @@
try { try {
put$Type$Internal(session, base, offset, value); put$Type$Internal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -32,7 +32,7 @@
private void put$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) { private void put$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
UNSAFE.put$Type$(base, offset, value); UNSAFE.put$Type$(base, offset, value);
} finally { } finally {
@ -46,7 +46,7 @@
try { try {
return get$Type$UnalignedInternal(session, base, offset, be); return get$Type$UnalignedInternal(session, base, offset, be);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -54,7 +54,7 @@
private $type$ get$Type$UnalignedInternal(MemorySessionImpl session, Object base, long offset, boolean be) { private $type$ get$Type$UnalignedInternal(MemorySessionImpl session, Object base, long offset, boolean be) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.get$Type$Unaligned(base, offset, be); return UNSAFE.get$Type$Unaligned(base, offset, be);
} finally { } finally {
@ -67,7 +67,7 @@
try { try {
put$Type$UnalignedInternal(session, base, offset, value, be); put$Type$UnalignedInternal(session, base, offset, value, be);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -75,7 +75,7 @@
private void put$Type$UnalignedInternal(MemorySessionImpl session, Object base, long offset, $type$ value, boolean be) { private void put$Type$UnalignedInternal(MemorySessionImpl session, Object base, long offset, $type$ value, boolean be) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
UNSAFE.put$Type$Unaligned(base, offset, value, be); UNSAFE.put$Type$Unaligned(base, offset, value, be);
} finally { } finally {
@ -89,7 +89,7 @@
try { try {
return get$Type$VolatileInternal(session, base, offset); return get$Type$VolatileInternal(session, base, offset);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -97,7 +97,7 @@
private $type$ get$Type$VolatileInternal(MemorySessionImpl session, Object base, long offset) { private $type$ get$Type$VolatileInternal(MemorySessionImpl session, Object base, long offset) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.get$Type$Volatile(base, offset); return UNSAFE.get$Type$Volatile(base, offset);
} finally { } finally {
@ -110,7 +110,7 @@
try { try {
put$Type$VolatileInternal(session, base, offset, value); put$Type$VolatileInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -118,7 +118,7 @@
private void put$Type$VolatileInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private void put$Type$VolatileInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
UNSAFE.put$Type$Volatile(base, offset, value); UNSAFE.put$Type$Volatile(base, offset, value);
} finally { } finally {
@ -131,7 +131,7 @@
try { try {
return get$Type$AcquireInternal(session, base, offset); return get$Type$AcquireInternal(session, base, offset);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -139,7 +139,7 @@
private $type$ get$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset) { private $type$ get$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.get$Type$Acquire(base, offset); return UNSAFE.get$Type$Acquire(base, offset);
} finally { } finally {
@ -152,7 +152,7 @@
try { try {
put$Type$ReleaseInternal(session, base, offset, value); put$Type$ReleaseInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -160,7 +160,7 @@
private void put$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private void put$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
UNSAFE.put$Type$Release(base, offset, value); UNSAFE.put$Type$Release(base, offset, value);
} finally { } finally {
@ -173,7 +173,7 @@
try { try {
return get$Type$OpaqueInternal(session, base, offset); return get$Type$OpaqueInternal(session, base, offset);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -181,7 +181,7 @@
private $type$ get$Type$OpaqueInternal(MemorySessionImpl session, Object base, long offset) { private $type$ get$Type$OpaqueInternal(MemorySessionImpl session, Object base, long offset) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.get$Type$Opaque(base, offset); return UNSAFE.get$Type$Opaque(base, offset);
} finally { } finally {
@ -193,7 +193,7 @@
try { try {
put$Type$OpaqueInternal(session, base, offset, value); put$Type$OpaqueInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -201,7 +201,7 @@
private void put$Type$OpaqueInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private void put$Type$OpaqueInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
UNSAFE.put$Type$Opaque(base, offset, value); UNSAFE.put$Type$Opaque(base, offset, value);
} finally { } finally {
@ -214,7 +214,7 @@
try { try {
return compareAndSet$Type$Internal(session, base, offset, expected, value); return compareAndSet$Type$Internal(session, base, offset, expected, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -222,7 +222,7 @@
private boolean compareAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) { private boolean compareAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.compareAndSet$Type$(base, offset, expected, value); return UNSAFE.compareAndSet$Type$(base, offset, expected, value);
} finally { } finally {
@ -235,7 +235,7 @@
try { try {
return compareAndExchange$Type$Internal(session, base, offset, expected, value); return compareAndExchange$Type$Internal(session, base, offset, expected, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -243,7 +243,7 @@
private $type$ compareAndExchange$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) { private $type$ compareAndExchange$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.compareAndExchange$Type$(base, offset, expected, value); return UNSAFE.compareAndExchange$Type$(base, offset, expected, value);
} finally { } finally {
@ -256,7 +256,7 @@
try { try {
return compareAndExchange$Type$AcquireInternal(session, base, offset, expected, value); return compareAndExchange$Type$AcquireInternal(session, base, offset, expected, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -264,7 +264,7 @@
private $type$ compareAndExchange$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) { private $type$ compareAndExchange$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.compareAndExchange$Type$Acquire(base, offset, expected, value); return UNSAFE.compareAndExchange$Type$Acquire(base, offset, expected, value);
} finally { } finally {
@ -277,7 +277,7 @@
try { try {
return compareAndExchange$Type$ReleaseInternal(session, base, offset, expected, value); return compareAndExchange$Type$ReleaseInternal(session, base, offset, expected, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -285,7 +285,7 @@
private $type$ compareAndExchange$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) { private $type$ compareAndExchange$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.compareAndExchange$Type$Release(base, offset, expected, value); return UNSAFE.compareAndExchange$Type$Release(base, offset, expected, value);
} finally { } finally {
@ -298,7 +298,7 @@
try { try {
return weakCompareAndSet$Type$PlainInternal(session, base, offset, expected, value); return weakCompareAndSet$Type$PlainInternal(session, base, offset, expected, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -306,7 +306,7 @@
private boolean weakCompareAndSet$Type$PlainInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) { private boolean weakCompareAndSet$Type$PlainInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.weakCompareAndSet$Type$Plain(base, offset, expected, value); return UNSAFE.weakCompareAndSet$Type$Plain(base, offset, expected, value);
} finally { } finally {
@ -319,7 +319,7 @@
try { try {
return weakCompareAndSet$Type$Internal(session, base, offset, expected, value); return weakCompareAndSet$Type$Internal(session, base, offset, expected, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -327,7 +327,7 @@
private boolean weakCompareAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) { private boolean weakCompareAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.weakCompareAndSet$Type$(base, offset, expected, value); return UNSAFE.weakCompareAndSet$Type$(base, offset, expected, value);
} finally { } finally {
@ -340,7 +340,7 @@
try { try {
return weakCompareAndSet$Type$AcquireInternal(session, base, offset, expected, value); return weakCompareAndSet$Type$AcquireInternal(session, base, offset, expected, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -348,7 +348,7 @@
private boolean weakCompareAndSet$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) { private boolean weakCompareAndSet$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.weakCompareAndSet$Type$Acquire(base, offset, expected, value); return UNSAFE.weakCompareAndSet$Type$Acquire(base, offset, expected, value);
} finally { } finally {
@ -361,7 +361,7 @@
try { try {
return weakCompareAndSet$Type$ReleaseInternal(session, base, offset, expected, value); return weakCompareAndSet$Type$ReleaseInternal(session, base, offset, expected, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -369,7 +369,7 @@
private boolean weakCompareAndSet$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) { private boolean weakCompareAndSet$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ expected, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.weakCompareAndSet$Type$Release(base, offset, expected, value); return UNSAFE.weakCompareAndSet$Type$Release(base, offset, expected, value);
} finally { } finally {
@ -382,7 +382,7 @@
try { try {
return getAndSet$Type$Internal(session, base, offset, value); return getAndSet$Type$Internal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -390,7 +390,7 @@
private $type$ getAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndSet$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndSet$Type$(base, offset, value); return UNSAFE.getAndSet$Type$(base, offset, value);
} finally { } finally {
@ -403,7 +403,7 @@
try { try {
return getAndSet$Type$AcquireInternal(session, base, offset, value); return getAndSet$Type$AcquireInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -411,7 +411,7 @@
private $type$ getAndSet$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndSet$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndSet$Type$Acquire(base, offset, value); return UNSAFE.getAndSet$Type$Acquire(base, offset, value);
} finally { } finally {
@ -424,7 +424,7 @@
try { try {
return getAndSet$Type$ReleaseInternal(session, base, offset, value); return getAndSet$Type$ReleaseInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -432,7 +432,7 @@
private $type$ getAndSet$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndSet$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndSet$Type$Release(base, offset, value); return UNSAFE.getAndSet$Type$Release(base, offset, value);
} finally { } finally {
@ -447,7 +447,7 @@
try { try {
return getAndAdd$Type$Internal(session, base, offset, delta); return getAndAdd$Type$Internal(session, base, offset, delta);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -455,7 +455,7 @@
private $type$ getAndAdd$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ delta) { private $type$ getAndAdd$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ delta) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndAdd$Type$(base, offset, delta); return UNSAFE.getAndAdd$Type$(base, offset, delta);
} finally { } finally {
@ -468,7 +468,7 @@
try { try {
return getAndAdd$Type$AcquireInternal(session, base, offset, delta); return getAndAdd$Type$AcquireInternal(session, base, offset, delta);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -476,7 +476,7 @@
private $type$ getAndAdd$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ delta) { private $type$ getAndAdd$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ delta) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndAdd$Type$Acquire(base, offset, delta); return UNSAFE.getAndAdd$Type$Acquire(base, offset, delta);
} finally { } finally {
@ -489,7 +489,7 @@
try { try {
return getAndAdd$Type$ReleaseInternal(session, base, offset, delta); return getAndAdd$Type$ReleaseInternal(session, base, offset, delta);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -497,7 +497,7 @@
private $type$ getAndAdd$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ delta) { private $type$ getAndAdd$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ delta) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndAdd$Type$Release(base, offset, delta); return UNSAFE.getAndAdd$Type$Release(base, offset, delta);
} finally { } finally {
@ -512,7 +512,7 @@
try { try {
return getAndBitwiseOr$Type$Internal(session, base, offset, value); return getAndBitwiseOr$Type$Internal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -520,7 +520,7 @@
private $type$ getAndBitwiseOr$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseOr$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseOr$Type$(base, offset, value); return UNSAFE.getAndBitwiseOr$Type$(base, offset, value);
} finally { } finally {
@ -533,7 +533,7 @@
try { try {
return getAndBitwiseOr$Type$AcquireInternal(session, base, offset, value); return getAndBitwiseOr$Type$AcquireInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -541,7 +541,7 @@
private $type$ getAndBitwiseOr$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseOr$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseOr$Type$Acquire(base, offset, value); return UNSAFE.getAndBitwiseOr$Type$Acquire(base, offset, value);
} finally { } finally {
@ -554,7 +554,7 @@
try { try {
return getAndBitwiseOr$Type$ReleaseInternal(session, base, offset, value); return getAndBitwiseOr$Type$ReleaseInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -562,7 +562,7 @@
private $type$ getAndBitwiseOr$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseOr$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseOr$Type$Release(base, offset, value); return UNSAFE.getAndBitwiseOr$Type$Release(base, offset, value);
} finally { } finally {
@ -575,7 +575,7 @@
try { try {
return getAndBitwiseAnd$Type$Internal(session, base, offset, value); return getAndBitwiseAnd$Type$Internal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -583,7 +583,7 @@
private $type$ getAndBitwiseAnd$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseAnd$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseAnd$Type$(base, offset, value); return UNSAFE.getAndBitwiseAnd$Type$(base, offset, value);
} finally { } finally {
@ -596,7 +596,7 @@
try { try {
return getAndBitwiseAnd$Type$AcquireInternal(session, base, offset, value); return getAndBitwiseAnd$Type$AcquireInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -604,7 +604,7 @@
private $type$ getAndBitwiseAnd$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseAnd$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseAnd$Type$Acquire(base, offset, value); return UNSAFE.getAndBitwiseAnd$Type$Acquire(base, offset, value);
} finally { } finally {
@ -617,7 +617,7 @@
try { try {
return getAndBitwiseAnd$Type$ReleaseInternal(session, base, offset, value); return getAndBitwiseAnd$Type$ReleaseInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -625,7 +625,7 @@
private $type$ getAndBitwiseAnd$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseAnd$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseAnd$Type$Release(base, offset, value); return UNSAFE.getAndBitwiseAnd$Type$Release(base, offset, value);
} finally { } finally {
@ -638,7 +638,7 @@
try { try {
return getAndBitwiseXor$Type$Internal(session, base, offset, value); return getAndBitwiseXor$Type$Internal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -646,7 +646,7 @@
private $type$ getAndBitwiseXor$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseXor$Type$Internal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseXor$Type$(base, offset, value); return UNSAFE.getAndBitwiseXor$Type$(base, offset, value);
} finally { } finally {
@ -659,7 +659,7 @@
try { try {
return getAndBitwiseXor$Type$AcquireInternal(session, base, offset, value); return getAndBitwiseXor$Type$AcquireInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -667,7 +667,7 @@
private $type$ getAndBitwiseXor$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseXor$Type$AcquireInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseXor$Type$Acquire(base, offset, value); return UNSAFE.getAndBitwiseXor$Type$Acquire(base, offset, value);
} finally { } finally {
@ -680,7 +680,7 @@
try { try {
return getAndBitwiseXor$Type$ReleaseInternal(session, base, offset, value); return getAndBitwiseXor$Type$ReleaseInternal(session, base, offset, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -688,7 +688,7 @@
private $type$ getAndBitwiseXor$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) { private $type$ getAndBitwiseXor$Type$ReleaseInternal(MemorySessionImpl session, Object base, long offset, $type$ value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return UNSAFE.getAndBitwiseXor$Type$Release(base, offset, value); return UNSAFE.getAndBitwiseXor$Type$Release(base, offset, value);
} finally { } finally {

View file

@ -32,6 +32,7 @@ import java.lang.annotation.Target;
import java.lang.foreign.MemorySegment; import java.lang.foreign.MemorySegment;
import java.lang.ref.Reference; import java.lang.ref.Reference;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.util.function.Supplier;
import jdk.internal.access.JavaNioAccess; import jdk.internal.access.JavaNioAccess;
import jdk.internal.access.SharedSecrets; import jdk.internal.access.SharedSecrets;
@ -55,10 +56,10 @@ import jdk.internal.vm.vector.VectorSupport;
* a memory region while another thread is releasing it. * a memory region while another thread is releasing it.
* <p> * <p>
* This class provides tools to manage races when multiple threads are accessing and/or releasing the same memory * This class provides tools to manage races when multiple threads are accessing and/or releasing the same memory
* region concurrently. More specifically, when a thread wants to release a memory region, it should call the * session concurrently. More specifically, when a thread wants to release a memory session, it should call the
* {@link MemorySessionImpl#close()} method. This method initiates thread-local handshakes with all the other VM threads, * {@link ScopedMemoryAccess#closeScope(MemorySessionImpl)} method. This method initiates thread-local handshakes with all the other VM threads,
* which are then stopped one by one. If any thread is found accessing a resource associated to the very memory session * which are then stopped one by one. If any thread is found accessing a resource associated to the very memory session
* being closed, the handshake fails, and the session cannot be closed. * being closed, the handshake fails, and the session will not be closed.
* <p> * <p>
* This synchronization strategy relies on the idea that accessing memory is atomic with respect to checking the * This synchronization strategy relies on the idea that accessing memory is atomic with respect to checking the
* validity of the session associated with that memory region - that is, a thread that wants to perform memory access will be * validity of the session associated with that memory region - that is, a thread that wants to perform memory access will be
@ -97,12 +98,20 @@ public class ScopedMemoryAccess {
} }
public static final class ScopedAccessError extends Error { public static final class ScopedAccessError extends Error {
private ScopedAccessError() {
super("Attempt to access an already released memory resource", null, false, false); @SuppressWarnings("serial")
private final Supplier<RuntimeException> runtimeExceptionSupplier;
public ScopedAccessError(Supplier<RuntimeException> runtimeExceptionSupplier) {
super("Invalid memory access", null, false, false);
this.runtimeExceptionSupplier = runtimeExceptionSupplier;
} }
static final long serialVersionUID = 1L; static final long serialVersionUID = 1L;
public static final ScopedAccessError INSTANCE = new ScopedAccessError(); public final RuntimeException newRuntimeException() {
return runtimeExceptionSupplier.get();
}
} }
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@ -112,64 +121,64 @@ public class ScopedMemoryAccess {
// bulk ops // bulk ops
@ForceInline @ForceInline
public void copyMemory(MemorySessionImpl srcScope, MemorySessionImpl dstScope, public void copyMemory(MemorySessionImpl srcSession, MemorySessionImpl dstSession,
Object srcBase, long srcOffset, Object srcBase, long srcOffset,
Object destBase, long destOffset, Object destBase, long destOffset,
long bytes) { long bytes) {
try { try {
copyMemoryInternal(srcScope, dstScope, srcBase, srcOffset, destBase, destOffset, bytes); copyMemoryInternal(srcSession, dstSession, srcBase, srcOffset, destBase, destOffset, bytes);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ForceInline @Scoped @ForceInline @Scoped
private void copyMemoryInternal(MemorySessionImpl srcScope, MemorySessionImpl dstScope, private void copyMemoryInternal(MemorySessionImpl srcSession, MemorySessionImpl dstSession,
Object srcBase, long srcOffset, Object srcBase, long srcOffset,
Object destBase, long destOffset, Object destBase, long destOffset,
long bytes) { long bytes) {
try { try {
if (srcScope != null) { if (srcSession != null) {
srcScope.checkValidState(); srcSession.checkValidStateRaw();
} }
if (dstScope != null) { if (dstSession != null) {
dstScope.checkValidState(); dstSession.checkValidStateRaw();
} }
UNSAFE.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes); UNSAFE.copyMemory(srcBase, srcOffset, destBase, destOffset, bytes);
} finally { } finally {
Reference.reachabilityFence(srcScope); Reference.reachabilityFence(srcSession);
Reference.reachabilityFence(dstScope); Reference.reachabilityFence(dstSession);
} }
} }
@ForceInline @ForceInline
public void copySwapMemory(MemorySessionImpl srcScope, MemorySessionImpl dstScope, public void copySwapMemory(MemorySessionImpl srcSession, MemorySessionImpl dstSession,
Object srcBase, long srcOffset, Object srcBase, long srcOffset,
Object destBase, long destOffset, Object destBase, long destOffset,
long bytes, long elemSize) { long bytes, long elemSize) {
try { try {
copySwapMemoryInternal(srcScope, dstScope, srcBase, srcOffset, destBase, destOffset, bytes, elemSize); copySwapMemoryInternal(srcSession, dstSession, srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ForceInline @Scoped @ForceInline @Scoped
private void copySwapMemoryInternal(MemorySessionImpl srcScope, MemorySessionImpl dstScope, private void copySwapMemoryInternal(MemorySessionImpl srcSession, MemorySessionImpl dstSession,
Object srcBase, long srcOffset, Object srcBase, long srcOffset,
Object destBase, long destOffset, Object destBase, long destOffset,
long bytes, long elemSize) { long bytes, long elemSize) {
try { try {
if (srcScope != null) { if (srcSession != null) {
srcScope.checkValidState(); srcSession.checkValidStateRaw();
} }
if (dstScope != null) { if (dstSession != null) {
dstScope.checkValidState(); dstSession.checkValidStateRaw();
} }
UNSAFE.copySwapMemory(srcBase, srcOffset, destBase, destOffset, bytes, elemSize); UNSAFE.copySwapMemory(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
} finally { } finally {
Reference.reachabilityFence(srcScope); Reference.reachabilityFence(srcSession);
Reference.reachabilityFence(dstScope); Reference.reachabilityFence(dstSession);
} }
} }
@ -178,7 +187,7 @@ public class ScopedMemoryAccess {
try { try {
setMemoryInternal(session, o, offset, bytes, value); setMemoryInternal(session, o, offset, bytes, value);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -186,7 +195,7 @@ public class ScopedMemoryAccess {
private void setMemoryInternal(MemorySessionImpl session, Object o, long offset, long bytes, byte value) { private void setMemoryInternal(MemorySessionImpl session, Object o, long offset, long bytes, byte value) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
UNSAFE.setMemory(o, offset, bytes, value); UNSAFE.setMemory(o, offset, bytes, value);
} finally { } finally {
@ -195,35 +204,35 @@ public class ScopedMemoryAccess {
} }
@ForceInline @ForceInline
public int vectorizedMismatch(MemorySessionImpl aScope, MemorySessionImpl bScope, public int vectorizedMismatch(MemorySessionImpl aSession, MemorySessionImpl bSession,
Object a, long aOffset, Object a, long aOffset,
Object b, long bOffset, Object b, long bOffset,
int length, int length,
int log2ArrayIndexScale) { int log2ArrayIndexScale) {
try { try {
return vectorizedMismatchInternal(aScope, bScope, a, aOffset, b, bOffset, length, log2ArrayIndexScale); return vectorizedMismatchInternal(aSession, bSession, a, aOffset, b, bOffset, length, log2ArrayIndexScale);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ForceInline @Scoped @ForceInline @Scoped
private int vectorizedMismatchInternal(MemorySessionImpl aScope, MemorySessionImpl bScope, private int vectorizedMismatchInternal(MemorySessionImpl aSession, MemorySessionImpl bSession,
Object a, long aOffset, Object a, long aOffset,
Object b, long bOffset, Object b, long bOffset,
int length, int length,
int log2ArrayIndexScale) { int log2ArrayIndexScale) {
try { try {
if (aScope != null) { if (aSession != null) {
aScope.checkValidState(); aSession.checkValidStateRaw();
} }
if (bScope != null) { if (bSession != null) {
bScope.checkValidState(); bSession.checkValidStateRaw();
} }
return ArraysSupport.vectorizedMismatch(a, aOffset, b, bOffset, length, log2ArrayIndexScale); return ArraysSupport.vectorizedMismatch(a, aOffset, b, bOffset, length, log2ArrayIndexScale);
} finally { } finally {
Reference.reachabilityFence(aScope); Reference.reachabilityFence(aSession);
Reference.reachabilityFence(bScope); Reference.reachabilityFence(bSession);
} }
} }
@ -232,7 +241,7 @@ public class ScopedMemoryAccess {
try { try {
return isLoadedInternal(session, address, isSync, size); return isLoadedInternal(session, address, isSync, size);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -240,7 +249,7 @@ public class ScopedMemoryAccess {
public boolean isLoadedInternal(MemorySessionImpl session, long address, boolean isSync, long size) { public boolean isLoadedInternal(MemorySessionImpl session, long address, boolean isSync, long size) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
return SharedSecrets.getJavaNioAccess().isLoaded(address, isSync, size); return SharedSecrets.getJavaNioAccess().isLoaded(address, isSync, size);
} finally { } finally {
@ -253,7 +262,7 @@ public class ScopedMemoryAccess {
try { try {
loadInternal(session, address, isSync, size); loadInternal(session, address, isSync, size);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -261,7 +270,7 @@ public class ScopedMemoryAccess {
public void loadInternal(MemorySessionImpl session, long address, boolean isSync, long size) { public void loadInternal(MemorySessionImpl session, long address, boolean isSync, long size) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
SharedSecrets.getJavaNioAccess().load(address, isSync, size); SharedSecrets.getJavaNioAccess().load(address, isSync, size);
} finally { } finally {
@ -274,7 +283,7 @@ public class ScopedMemoryAccess {
try { try {
unloadInternal(session, address, isSync, size); unloadInternal(session, address, isSync, size);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -282,7 +291,7 @@ public class ScopedMemoryAccess {
public void unloadInternal(MemorySessionImpl session, long address, boolean isSync, long size) { public void unloadInternal(MemorySessionImpl session, long address, boolean isSync, long size) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
SharedSecrets.getJavaNioAccess().unload(address, isSync, size); SharedSecrets.getJavaNioAccess().unload(address, isSync, size);
} finally { } finally {
@ -295,7 +304,7 @@ public class ScopedMemoryAccess {
try { try {
forceInternal(session, fd, address, isSync, index, length); forceInternal(session, fd, address, isSync, index, length);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -303,7 +312,7 @@ public class ScopedMemoryAccess {
public void forceInternal(MemorySessionImpl session, FileDescriptor fd, long address, boolean isSync, long index, long length) { public void forceInternal(MemorySessionImpl session, FileDescriptor fd, long address, boolean isSync, long index, long length) {
try { try {
if (session != null) { if (session != null) {
session.checkValidState(); session.checkValidStateRaw();
} }
SharedSecrets.getJavaNioAccess().force(fd, address, isSync, index, length); SharedSecrets.getJavaNioAccess().force(fd, address, isSync, index, length);
} finally { } finally {
@ -333,7 +342,7 @@ public class ScopedMemoryAccess {
s, s,
defaultImpl); defaultImpl);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -347,7 +356,7 @@ public class ScopedMemoryAccess {
S s, S s,
VectorSupport.LoadOperation<AbstractMemorySegmentImpl, V, S> defaultImpl) { VectorSupport.LoadOperation<AbstractMemorySegmentImpl, V, S> defaultImpl) {
try { try {
session.checkValidState(); session.checkValidStateRaw();
return VectorSupport.load(vmClass, e, length, return VectorSupport.load(vmClass, e, length,
msp.unsafeGetBase(), msp.unsafeGetOffset() + offset, msp.unsafeGetBase(), msp.unsafeGetOffset() + offset,
@ -378,7 +387,7 @@ public class ScopedMemoryAccess {
s, offsetInRange, s, offsetInRange,
defaultImpl); defaultImpl);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -393,7 +402,7 @@ public class ScopedMemoryAccess {
S s, int offsetInRange, S s, int offsetInRange,
VectorSupport.LoadVectorMaskedOperation<AbstractMemorySegmentImpl, V, S, M> defaultImpl) { VectorSupport.LoadVectorMaskedOperation<AbstractMemorySegmentImpl, V, S, M> defaultImpl) {
try { try {
session.checkValidState(); session.checkValidStateRaw();
return VectorSupport.loadMasked(vmClass, maskClass, e, length, return VectorSupport.loadMasked(vmClass, maskClass, e, length,
msp.unsafeGetBase(), msp.unsafeGetOffset() + offset, m, offsetInRange, msp.unsafeGetBase(), msp.unsafeGetOffset() + offset, m, offsetInRange,
@ -424,7 +433,7 @@ public class ScopedMemoryAccess {
msp, offset, msp, offset,
defaultImpl); defaultImpl);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -438,7 +447,7 @@ public class ScopedMemoryAccess {
AbstractMemorySegmentImpl msp, long offset, AbstractMemorySegmentImpl msp, long offset,
VectorSupport.StoreVectorOperation<AbstractMemorySegmentImpl, V> defaultImpl) { VectorSupport.StoreVectorOperation<AbstractMemorySegmentImpl, V> defaultImpl) {
try { try {
session.checkValidState(); session.checkValidStateRaw();
VectorSupport.store(vmClass, e, length, VectorSupport.store(vmClass, e, length,
msp.unsafeGetBase(), msp.unsafeGetOffset() + offset, msp.unsafeGetBase(), msp.unsafeGetOffset() + offset,
@ -470,7 +479,7 @@ public class ScopedMemoryAccess {
msp, offset, msp, offset,
defaultImpl); defaultImpl);
} catch (ScopedAccessError ex) { } catch (ScopedAccessError ex) {
throw new IllegalStateException("This segment is already closed"); throw ex.newRuntimeException();
} }
} }
@ -484,7 +493,7 @@ public class ScopedMemoryAccess {
AbstractMemorySegmentImpl msp, long offset, AbstractMemorySegmentImpl msp, long offset,
VectorSupport.StoreVectorMaskedOperation<AbstractMemorySegmentImpl, V, M> defaultImpl) { VectorSupport.StoreVectorMaskedOperation<AbstractMemorySegmentImpl, V, M> defaultImpl) {
try { try {
session.checkValidState(); session.checkValidStateRaw();
VectorSupport.storeMasked(vmClass, maskClass, e, length, VectorSupport.storeMasked(vmClass, maskClass, e, length,
msp.unsafeGetBase(), msp.unsafeGetOffset() + offset, msp.unsafeGetBase(), msp.unsafeGetOffset() + offset,

View file

@ -1199,9 +1199,6 @@ public class FileChannelImpl
} }
} }
private static final int MAP_MEM_SEG_DEFAULT_MODES = 0;
private static final int MAP_MEM_SEG_READ_ONLY = 1;
@Override @Override
public MemorySegment map(MapMode mode, long offset, long size, public MemorySegment map(MapMode mode, long offset, long size,
MemorySession session) MemorySession session)
@ -1210,7 +1207,7 @@ public class FileChannelImpl
Objects.requireNonNull(mode,"Mode is null"); Objects.requireNonNull(mode,"Mode is null");
Objects.requireNonNull(session, "Session is null"); Objects.requireNonNull(session, "Session is null");
MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session); MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session);
sessionImpl.checkValidStateSlow(); sessionImpl.checkValidState();
if (offset < 0) if (offset < 0)
throw new IllegalArgumentException("Requested bytes offset must be >= 0."); throw new IllegalArgumentException("Requested bytes offset must be >= 0.");
if (size < 0) if (size < 0)
@ -1219,14 +1216,14 @@ public class FileChannelImpl
boolean isSync = isSync(mode); boolean isSync = isSync(mode);
int prot = toProt(mode); int prot = toProt(mode);
Unmapper unmapper = mapInternal(mode, offset, size, prot, isSync); Unmapper unmapper = mapInternal(mode, offset, size, prot, isSync);
int modes = MAP_MEM_SEG_DEFAULT_MODES; boolean readOnly = false;
if (mode == MapMode.READ_ONLY) { if (mode == MapMode.READ_ONLY) {
modes |= MAP_MEM_SEG_READ_ONLY; readOnly = true;
} }
if (unmapper != null) { if (unmapper != null) {
AbstractMemorySegmentImpl segment = AbstractMemorySegmentImpl segment =
new MappedMemorySegmentImpl(unmapper.address(), unmapper, size, new MappedMemorySegmentImpl(unmapper.address(), unmapper, size,
modes, session); readOnly, session);
MemorySessionImpl.ResourceList.ResourceCleanup resource = MemorySessionImpl.ResourceList.ResourceCleanup resource =
new MemorySessionImpl.ResourceList.ResourceCleanup() { new MemorySessionImpl.ResourceList.ResourceCleanup() {
@Override @Override
@ -1237,7 +1234,7 @@ public class FileChannelImpl
sessionImpl.addOrCleanupIfFail(resource); sessionImpl.addOrCleanupIfFail(resource);
return segment; return segment;
} else { } else {
return new MappedMemorySegmentImpl.EmptyMappedMemorySegmentImpl(modes, session); return new MappedMemorySegmentImpl.EmptyMappedMemorySegmentImpl(readOnly, sessionImpl);
} }
} }

View file

@ -373,7 +373,7 @@ public class TestByteBuffer {
Throwable cause = ex.getCause(); Throwable cause = ex.getCause();
if (cause instanceof IllegalStateException) { if (cause instanceof IllegalStateException) {
//all get/set buffer operation should fail because of the session check //all get/set buffer operation should fail because of the session check
assertTrue(ex.getCause().getMessage().contains("already closed")); assertTrue(ex.getCause().getMessage().contains("Already closed"));
} else { } else {
//all other exceptions were unexpected - fail //all other exceptions were unexpected - fail
fail("Unexpected exception", cause); fail("Unexpected exception", cause);
@ -410,7 +410,7 @@ public class TestByteBuffer {
handle.invoke(e.getValue()); handle.invoke(e.getValue());
fail(); fail();
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
assertTrue(ex.getMessage().contains("already closed")); assertTrue(ex.getMessage().contains("Already closed"));
} catch (UnsupportedOperationException ex) { } catch (UnsupportedOperationException ex) {
//skip //skip
} catch (Throwable ex) { } catch (Throwable ex) {

View file

@ -370,8 +370,8 @@ public class TestMemorySession {
} }
private void keepAlive(MemorySession child, MemorySession parent) { private void keepAlive(MemorySession child, MemorySession parent) {
MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(parent); MemorySessionImpl parentImpl = MemorySessionImpl.toSessionImpl(parent);
sessionImpl.acquire0(); parentImpl.acquire0();
child.addCloseAction(sessionImpl::release0); child.addCloseAction(parentImpl::release0);
} }
} }