mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8287809: Revisit implementation of memory session
Reviewed-by: jvernee
This commit is contained in:
parent
cb6e9cb728
commit
fed3af8ae0
21 changed files with 328 additions and 383 deletions
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue