8318966: Some methods make promises about Java array element alignment that are too strong

Reviewed-by: psandoz, mcimadamore
This commit is contained in:
Jorn Vernee 2024-02-14 14:30:54 +00:00
parent 737b4c515e
commit 9c852df6aa
19 changed files with 1850 additions and 4678 deletions

View file

@ -4513,48 +4513,18 @@ return mh1;
* or greater than the {@code byte[]} array length minus the size (in bytes)
* of {@code T}.
* <p>
* Access of bytes at an index may be aligned or misaligned for {@code T},
* with respect to the underlying memory address, {@code A} say, associated
* with the array and index.
* If access is misaligned then access for anything other than the
* {@code get} and {@code set} access modes will result in an
* {@code IllegalStateException}. In such cases atomic access is only
* guaranteed with respect to the largest power of two that divides the GCD
* of {@code A} and the size (in bytes) of {@code T}.
* If access is aligned then following access modes are supported and are
* guaranteed to support atomic access:
* <ul>
* <li>read write access modes for all {@code T}, with the exception of
* access modes {@code get} and {@code set} for {@code long} and
* {@code double} on 32-bit platforms.
* <li>atomic update access modes for {@code int}, {@code long},
* {@code float} or {@code double}.
* (Future major platform releases of the JDK may support additional
* types for certain currently unsupported access modes.)
* <li>numeric atomic update access modes for {@code int} and {@code long}.
* (Future major platform releases of the JDK may support additional
* numeric types for certain currently unsupported access modes.)
* <li>bitwise atomic update access modes for {@code int} and {@code long}.
* (Future major platform releases of the JDK may support additional
* numeric types for certain currently unsupported access modes.)
* </ul>
* <p>
* Misaligned access, and therefore atomicity guarantees, may be determined
* for {@code byte[]} arrays without operating on a specific array. Given
* an {@code index}, {@code T} and its corresponding boxed type,
* {@code T_BOX}, misalignment may be determined as follows:
* <pre>{@code
* int sizeOfT = T_BOX.BYTES; // size in bytes of T
* int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]).
* alignmentOffset(0, sizeOfT);
* int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
* boolean isMisaligned = misalignedAtIndex != 0;
* }</pre>
* <p>
* If the variable type is {@code float} or {@code double} then atomic
* update access modes compare values using their bitwise representation
* (see {@link Float#floatToRawIntBits} and
* {@link Double#doubleToRawLongBits}, respectively).
* Only plain {@linkplain VarHandle.AccessMode#GET get} and {@linkplain VarHandle.AccessMode#SET set}
* access modes are supported by the returned var handle. For all other access modes, an
* {@link UnsupportedOperationException} will be thrown.
*
* @apiNote if access modes other than plain access are required, clients should
* consider using off-heap memory through
* {@linkplain java.nio.ByteBuffer#allocateDirect(int) direct byte buffers} or
* off-heap {@linkplain java.lang.foreign.MemorySegment memory segments},
* or memory segments backed by a
* {@linkplain java.lang.foreign.MemorySegment#ofArray(long[]) {@code long[]}},
* for which stronger alignment guarantees can be made.
*
* @param viewArrayClass the view array class, with a component type of
* type {@code T}
* @param byteOrder the endianness of the view array elements, as
@ -4600,7 +4570,13 @@ return mh1;
* or greater than the {@code ByteBuffer} limit minus the size (in bytes) of
* {@code T}.
* <p>
* Access of bytes at an index may be aligned or misaligned for {@code T},
* For heap byte buffers, access is always unaligned. As a result, only the plain
* {@linkplain VarHandle.AccessMode#GET get}
* and {@linkplain VarHandle.AccessMode#SET set} access modes are supported by the
* returned var handle. For all other access modes, an {@link IllegalStateException}
* will be thrown.
* <p>
* For direct buffers only, access of bytes at an index may be aligned or misaligned for {@code T},
* with respect to the underlying memory address, {@code A} say, associated
* with the {@code ByteBuffer} and index.
* If access is misaligned then access for anything other than the

View file

@ -49,7 +49,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
static final int ALIGN = $BoxType$.BYTES - 1;
static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
#if[floatingPoint]
@ -115,14 +115,6 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
return Preconditions.checkIndex(index, ba.length - ALIGN, Preconditions.AIOOBE_FORMATTER);
}
@ForceInline
static long address(byte[] ba, int index) {
long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET;
if ((address & ALIGN) != 0)
throw newIllegalStateExceptionForMisalignedAccess(index);
return address;
}
@ForceInline
static $type$ get(VarHandle ob, Object oba, int index) {
ArrayHandle handle = (ArrayHandle)ob;
@ -160,419 +152,6 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
#end[floatingPoint]
}
@ForceInline
static $type$ getVolatile(VarHandle ob, Object oba, int index) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.get$RawType$Volatile(
ba,
address(ba, index(ba, index))));
}
@ForceInline
static void setVolatile(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
UNSAFE.put$RawType$Volatile(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value));
}
@ForceInline
static $type$ getAcquire(VarHandle ob, Object oba, int index) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.get$RawType$Acquire(
ba,
address(ba, index(ba, index))));
}
@ForceInline
static void setRelease(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
UNSAFE.put$RawType$Release(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value));
}
@ForceInline
static $type$ getOpaque(VarHandle ob, Object oba, int index) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.get$RawType$Opaque(
ba,
address(ba, index(ba, index))));
}
@ForceInline
static void setOpaque(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
UNSAFE.put$RawType$Opaque(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value));
}
#if[CAS]
@ForceInline
static boolean compareAndSet(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
#if[Object]
return UNSAFE.compareAndSetReference(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
#else[Object]
return UNSAFE.compareAndSet$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
#end[Object]
}
@ForceInline
static $type$ compareAndExchange(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static $type$ compareAndExchangeAcquire(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$Acquire(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static $type$ compareAndExchangeRelease(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$Release(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static boolean weakCompareAndSetPlain(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return UNSAFE.weakCompareAndSet$RawType$Plain(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static boolean weakCompareAndSet(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return UNSAFE.weakCompareAndSet$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static boolean weakCompareAndSetAcquire(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return UNSAFE.weakCompareAndSet$RawType$Acquire(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static boolean weakCompareAndSetRelease(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return UNSAFE.weakCompareAndSet$RawType$Release(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static $type$ getAndSet(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
#if[Object]
return convEndian(handle.be,
UNSAFE.getAndSetReference(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value)));
#else[Object]
return convEndian(handle.be,
UNSAFE.getAndSet$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value)));
#end[Object]
}
@ForceInline
static $type$ getAndSetAcquire(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.getAndSet$RawType$Acquire(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value)));
}
@ForceInline
static $type$ getAndSetRelease(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.getAndSet$RawType$Release(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value)));
}
#end[CAS]
#if[AtomicAdd]
@ForceInline
static $type$ getAndAdd(VarHandle ob, Object oba, int index, $type$ delta) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndAdd$RawType$(
ba,
address(ba, index(ba, index)),
delta);
} else {
return getAndAddConvEndianWithCAS(ba, index, delta);
}
}
@ForceInline
static $type$ getAndAddAcquire(VarHandle ob, Object oba, int index, $type$ delta) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndAdd$RawType$Acquire(
ba,
address(ba, index(ba, index)),
delta);
} else {
return getAndAddConvEndianWithCAS(ba, index, delta);
}
}
@ForceInline
static $type$ getAndAddRelease(VarHandle ob, Object oba, int index, $type$ delta) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndAdd$RawType$Release(
ba,
address(ba, index(ba, index)),
delta);
} else {
return getAndAddConvEndianWithCAS(ba, index, delta);
}
}
@ForceInline
static $type$ getAndAddConvEndianWithCAS(byte[] ba, int index, $type$ delta) {
$type$ nativeExpectedValue, expectedValue;
long offset = address(ba, index(ba, index));
do {
nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
} while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset,
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
return expectedValue;
}
#end[AtomicAdd]
#if[Bitwise]
@ForceInline
static $type$ getAndBitwiseOr(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseOr$RawType$(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseOrConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseOrRelease(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseOr$RawType$Release(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseOrConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseOr$RawType$Acquire(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseOrConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseOrConvEndianWithCAS(byte[] ba, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
long offset = address(ba, index(ba, index));
do {
nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
} while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset,
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue | value)));
return expectedValue;
}
@ForceInline
static $type$ getAndBitwiseAnd(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseAnd$RawType$(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseAndConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseAndRelease(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseAnd$RawType$Release(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseAndConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseAnd$RawType$Acquire(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseAndConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseAndConvEndianWithCAS(byte[] ba, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
long offset = address(ba, index(ba, index));
do {
nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
} while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset,
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue & value)));
return expectedValue;
}
@ForceInline
static $type$ getAndBitwiseXor(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseXor$RawType$(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseXorConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseXorRelease(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseXor$RawType$Release(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseXorConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object oba, int index, $type$ value) {
ArrayHandle handle = (ArrayHandle)ob;
byte[] ba = (byte[]) oba;
if (handle.be == BE) {
return UNSAFE.getAndBitwiseXor$RawType$Acquire(
ba,
address(ba, index(ba, index)),
value);
} else {
return getAndBitwiseXorConvEndianWithCAS(ba, index, value);
}
}
@ForceInline
static $type$ getAndBitwiseXorConvEndianWithCAS(byte[] ba, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
long offset = address(ba, index(ba, index));
do {
nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
} while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset,
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue ^ value)));
return expectedValue;
}
#end[Bitwise]
static final VarForm FORM = new VarForm(ArrayHandle.class, byte[].class, $type$.class, int.class);
}
@ -634,6 +213,14 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
return address;
}
@ForceInline
static Object checkNullHeapBase(Object hb) {
if (hb != null) {
throw new IllegalStateException("Atomic access not supported for heap buffer");
}
return hb;
}
@ForceInline
static $type$ get(VarHandle ob, Object obb, int index) {
ByteBufferHandle handle = (ByteBufferHandle)ob;
@ -677,7 +264,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, index(bb, index))));
}
@ -686,7 +273,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
SCOPED_MEMORY_ACCESS.put$RawType$Volatile(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
@ -697,7 +284,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.get$RawType$Acquire(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, index(bb, index))));
}
@ -706,7 +293,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
SCOPED_MEMORY_ACCESS.put$RawType$Release(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
@ -717,7 +304,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.get$RawType$Opaque(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, index(bb, index))));
}
@ -726,7 +313,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
SCOPED_MEMORY_ACCESS.put$RawType$Opaque(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
@ -736,17 +323,10 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
static boolean compareAndSet(VarHandle ob, Object obb, int index, $type$ expected, $type$ value) {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
#if[Object]
return SCOPED_MEMORY_ACCESS.compareAndSetReference(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
#else[Object]
return SCOPED_MEMORY_ACCESS.compareAndSet$RawType$(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
#end[Object]
}
@ForceInline
@ -755,7 +335,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ -766,7 +346,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Acquire(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ -777,7 +357,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Release(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ -787,7 +367,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Plain(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ -797,7 +377,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ -807,7 +387,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Acquire(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ -817,7 +397,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Release(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ -826,19 +406,11 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
static $type$ getAndSet(VarHandle ob, Object obb, int index, $type$ value) {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
#if[Object]
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.getAndSetReference(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
#else[Object]
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.getAndSet$RawType$(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
#end[Object]
}
@ForceInline
@ -847,7 +419,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Acquire(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
}
@ -858,7 +430,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Release(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
}
@ -871,7 +443,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
delta);
} else {
@ -885,7 +457,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Acquire(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
delta);
} else {
@ -899,7 +471,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Release(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
delta);
} else {
@ -910,7 +482,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
@ForceInline
static $type$ getAndAddConvEndianWithCAS(ByteBuffer bb, int index, $type$ delta) {
$type$ nativeExpectedValue, expectedValue;
Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB);
Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB));
long offset = address(bb, indexRO(bb, index));
do {
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset);
@ -928,7 +500,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -942,7 +514,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Release(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -956,7 +528,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Acquire(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -967,7 +539,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
@ForceInline
static $type$ getAndBitwiseOrConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB);
Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB));
long offset = address(bb, indexRO(bb, index));
do {
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset);
@ -983,7 +555,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -997,7 +569,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Release(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -1011,7 +583,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Acquire(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -1022,7 +594,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
@ForceInline
static $type$ getAndBitwiseAndConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB);
Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB));
long offset = address(bb, indexRO(bb, index));
do {
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset);
@ -1039,7 +611,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -1053,7 +625,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Release(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -1067,7 +639,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Acquire(session(bb),
UNSAFE.getReference(bb, BYTE_BUFFER_HB),
checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@ -1078,7 +650,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
@ForceInline
static $type$ getAndBitwiseXorConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB);
Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB));
long offset = address(bb, indexRO(bb, index));
do {
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset);

View file

@ -1557,7 +1557,7 @@ public abstract sealed class $Type$Buffer
super.position(newPosition);
return this;
}
/**
* {@inheritDoc}
* @since 9
@ -1571,13 +1571,13 @@ public abstract sealed class $Type$Buffer
super.limit(newLimit);
return this;
}
/**
* {@inheritDoc}
* @since 9
*/
@Override
public
public
#if[!byte]
final
#end[!byte]
@ -1591,7 +1591,7 @@ public abstract sealed class $Type$Buffer
* @since 9
*/
@Override
public
public
#if[!byte]
final
#end[!byte]
@ -1605,7 +1605,7 @@ public abstract sealed class $Type$Buffer
* @since 9
*/
@Override
public
public
#if[!byte]
final
#end[!byte]
@ -1619,7 +1619,7 @@ public abstract sealed class $Type$Buffer
* @since 9
*/
@Override
public
public
#if[!byte]
final
#end[!byte]
@ -1633,7 +1633,7 @@ public abstract sealed class $Type$Buffer
* @since 9
*/
@Override
public
public
#if[!byte]
final
#end[!byte]
@ -2208,15 +2208,11 @@ public abstract sealed class $Type$Buffer
* alignmentOffset(index + (unitSize - value), unitSize) == 0
* }
* must hold.
*
*
* @apiNote
* This method may be utilized to determine if unit size bytes from an
* index can be accessed atomically, if supported by the native platform.
*
* @implNote
* This implementation throws {@code UnsupportedOperationException} for
* non-direct buffers when the given unit size is greater then {@code 8}.
*
* @param index
* The index to query for alignment offset, must be non-negative, no
* upper bounds check is performed
@ -2231,13 +2227,7 @@ public abstract sealed class $Type$Buffer
* {@code 2}
*
* @throws UnsupportedOperationException
* If the native platform does not guarantee stable alignment offset
* values for the given unit size when managing the memory regions
* of buffers of the same kind as this buffer (direct or
* non-direct). For example, if garbage collection would result
* in the moving of a memory region covered by a non-direct buffer
* from one location to another and both locations have different
* alignment characteristics.
* If the buffer is non-direct, and {@code unitSize > 1}
*
* @see #alignedSlice(int)
* @since 9
@ -2247,7 +2237,7 @@ public abstract sealed class $Type$Buffer
throw new IllegalArgumentException("Index less than zero: " + index);
if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
if (unitSize > 8 && !isDirect())
if (unitSize > 1 && !isDirect())
throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
return (int) ((address + index) & (unitSize - 1));
@ -2287,10 +2277,6 @@ public abstract sealed class $Type$Buffer
* from index, that is a multiple of the unit size, may be accessed
* atomically, if supported by the native platform.
*
* @implNote
* This implementation throws {@code UnsupportedOperationException} for
* non-direct buffers when the given unit size is greater then {@code 8}.
*
* @param unitSize
* The unit size in bytes, must be a power of {@code 2}
*
@ -2300,13 +2286,7 @@ public abstract sealed class $Type$Buffer
* If the unit size not a power of {@code 2}
*
* @throws UnsupportedOperationException
* If the native platform does not guarantee stable aligned slices
* for the given unit size when managing the memory regions
* of buffers of the same kind as this buffer (direct or
* non-direct). For example, if garbage collection would result
* in the moving of a memory region covered by a non-direct buffer
* from one location to another and both locations have different
* alignment characteristics.
* If the buffer is non-direct, and {@code unitSize > 1}
*
* @see #alignmentOffset(int, int)
* @see #slice()