8278897: Alignment of heap segments is not enforced correctly
Reviewed-by: jvernee
This commit is contained in:
parent
0f4807e8fe
commit
9d43d25da8
@ -50,7 +50,7 @@ abstract class MemoryAccessVarHandleBase extends VarHandle {
|
||||
this.alignmentMask = alignmentMask;
|
||||
}
|
||||
|
||||
static IllegalStateException newIllegalStateExceptionForMisalignedAccess(long address) {
|
||||
return new IllegalStateException("Misaligned access at address: " + address);
|
||||
static IllegalArgumentException newIllegalArgumentExceptionForMisalignedAccess(long address) {
|
||||
return new IllegalArgumentException("Misaligned access at address: " + address);
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ final class MemoryAccessVarHandle$Type$Helper extends MemoryAccessVarHandleBase
|
||||
static long offset(boolean skipAlignmentMaskCheck, MemorySegmentProxy bb, long offset, long alignmentMask) {
|
||||
long address = offsetNoVMAlignCheck(skipAlignmentMaskCheck, bb, offset, alignmentMask);
|
||||
if ((address & VM_ALIGN) != 0) {
|
||||
throw MemoryAccessVarHandleBase.newIllegalStateExceptionForMisalignedAccess(address);
|
||||
throw MemoryAccessVarHandleBase.newIllegalArgumentExceptionForMisalignedAccess(address);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
@ -115,14 +115,15 @@ final class MemoryAccessVarHandle$Type$Helper extends MemoryAccessVarHandleBase
|
||||
static long offsetNoVMAlignCheck(boolean skipAlignmentMaskCheck, MemorySegmentProxy bb, long offset, long alignmentMask) {
|
||||
long base = bb.unsafeGetOffset();
|
||||
long address = base + offset;
|
||||
long maxAlignMask = bb.maxAlignMask();
|
||||
if (skipAlignmentMaskCheck) {
|
||||
//note: the offset portion has already been aligned-checked, by construction
|
||||
if ((base & alignmentMask) != 0) {
|
||||
throw MemoryAccessVarHandleBase.newIllegalStateExceptionForMisalignedAccess(address);
|
||||
if (((base | maxAlignMask) & alignmentMask) != 0) {
|
||||
throw MemoryAccessVarHandleBase.newIllegalArgumentExceptionForMisalignedAccess(address);
|
||||
}
|
||||
} else {
|
||||
if ((address & alignmentMask) != 0) {
|
||||
throw MemoryAccessVarHandleBase.newIllegalStateExceptionForMisalignedAccess(address);
|
||||
if (((address | maxAlignMask) & alignmentMask) != 0) {
|
||||
throw MemoryAccessVarHandleBase.newIllegalArgumentExceptionForMisalignedAccess(address);
|
||||
}
|
||||
}
|
||||
return address;
|
||||
|
@ -44,6 +44,7 @@ public abstract class MemorySegmentProxy {
|
||||
public abstract Object unsafeGetBase();
|
||||
public abstract boolean isSmall();
|
||||
public abstract ScopedMemoryAccess.Scope scope();
|
||||
public abstract long maxAlignMask();
|
||||
|
||||
/* Helper functions for offset computations. These are required so that we can avoid issuing long opcodes
|
||||
* (e.g. LMUL, LADD) when we're operating on 'small' segments (segments whose length can be expressed with an int).
|
||||
|
@ -174,6 +174,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return a byte value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -192,6 +194,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the byte value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -210,6 +214,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return a boolean value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -228,6 +234,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the boolean value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -246,6 +254,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return a char value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -264,6 +274,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the char value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -282,6 +294,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return a short value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -300,6 +314,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the short value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -318,6 +334,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return an int value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -336,6 +354,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the int value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -354,6 +374,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return a float value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -372,6 +394,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the float value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -390,6 +414,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return a long value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -408,6 +434,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the long value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -426,6 +454,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return a double value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -444,6 +474,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the double value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -462,6 +494,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @return an address value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -480,6 +514,8 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param offset offset in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + offset}.
|
||||
* @param value the address value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -498,6 +534,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @return a char value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -516,6 +555,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @param value the char value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -534,6 +576,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @return a short value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -552,6 +597,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @param value the short value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -570,6 +618,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @return an int value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -588,6 +639,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @param value the int value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -606,6 +660,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @return a float value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -624,6 +681,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @param value the float value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -642,6 +702,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @return a long value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -660,6 +723,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @param value the long value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -678,6 +744,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @return a double value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -696,6 +765,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @param value the double value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -714,6 +786,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be read.
|
||||
* @param index index in bytes (relative to this address). The final address of this read operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @return an address value read from this address.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
@ -732,6 +807,9 @@ public sealed interface MemoryAddress extends Addressable permits MemoryAddressI
|
||||
* @param layout the layout of the memory region to be written.
|
||||
* @param index index in bytes (relative to this address). The final address of this write operation can be expressed as {@code toRowLongValue() + (index * layout.byteSize())}.
|
||||
* @param value the address value to be written.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
|
||||
* {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
|
||||
* {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
|
||||
|
@ -139,6 +139,56 @@ import java.util.stream.Stream;
|
||||
* {@linkplain MemoryHandles#varHandle(ValueLayout) value layout}, and then adapt it using the var handle combinator
|
||||
* functions defined in the {@link MemoryHandles} class.
|
||||
*
|
||||
* <h2 id="segment-alignment">Alignment</h2>
|
||||
*
|
||||
* When dereferencing a memory segment using a layout, the runtime must check that the segment address being dereferenced
|
||||
* matches the layout's {@linkplain MemoryLayout#byteAlignment() alignment constraints}. If the segment being
|
||||
* dereferenced is a native segment, then it has a concrete {@linkplain #address() base address}, which can
|
||||
* be used to perform the alignment check. The pseudo-function below demonstrates this:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
boolean isAligned(MemorySegment segment, long offset, MemoryLayout layout) {
|
||||
return ((segment.address().toRawLongValue() + offset) % layout.byteAlignment()) == 0
|
||||
}
|
||||
* }</pre></blockquote>
|
||||
*
|
||||
* If, however, the segment being dereferenced is a heap segment, the above function will not work: a heap
|
||||
* segment's base address is <em>virtualized</em> and, as such, cannot be used to construct an alignment check. Instead,
|
||||
* heap segments are assumed to produce addresses which are never more aligned than the element size of the Java array from which
|
||||
* they have originated from, as shown in the following table:
|
||||
*
|
||||
* <blockquote><table class="plain">
|
||||
* <caption style="display:none">Array type of an array backing a segment and its address alignment</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th scope="col">Array type</th>
|
||||
* <th scope="col">Alignment</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><th scope="row" style="font-weight:normal">{@code boolean[]}</th>
|
||||
* <td style="text-align:center;">{@code 1}</td></tr>
|
||||
* <tr><th scope="row" style="font-weight:normal">{@code byte[]}</th>
|
||||
* <td style="text-align:center;">{@code 1}</td></tr>
|
||||
* <tr><th scope="row" style="font-weight:normal">{@code char[]}</th>
|
||||
* <td style="text-align:center;">{@code 2}</td></tr>
|
||||
* <tr><th scope="row" style="font-weight:normal">{@code short[]}</th>
|
||||
* <td style="text-align:center;">{@code 2}</td></tr>
|
||||
* <tr><th scope="row" style="font-weight:normal">{@code int[]}</th>
|
||||
* <td style="text-align:center;">{@code 4}</td></tr>
|
||||
* <tr><th scope="row" style="font-weight:normal">{@code float[]}</th>
|
||||
* <td style="text-align:center;">{@code 4}</td></tr>
|
||||
* <tr><th scope="row" style="font-weight:normal">{@code long[]}</th>
|
||||
* <td style="text-align:center;">{@code 8}</td></tr>
|
||||
* <tr><th scope="row" style="font-weight:normal">{@code double[]}</th>
|
||||
* <td style="text-align:center;">{@code 8}</td></tr>
|
||||
* </tbody>
|
||||
* </table></blockquote>
|
||||
*
|
||||
* Note that the above definition is conservative: it might be possible, for instance, that a heap segment
|
||||
* constructed from a {@code byte[]} might have a subset of addresses {@code S} which happen to be 8-byte aligned. But determining
|
||||
* which segment addresses belong to {@code S} requires reasoning about details which are ultimately implementation-dependent.
|
||||
*
|
||||
* <h2>Lifecycle and confinement</h2>
|
||||
*
|
||||
* Memory segments are associated with a resource scope (see {@link ResourceScope}), which can be accessed using
|
||||
@ -226,7 +276,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param elementLayout the layout to be used for splitting.
|
||||
* @return the element spliterator for this segment
|
||||
* @throws IllegalArgumentException if the {@code elementLayout} size is zero, or the segment size modulo the
|
||||
* {@code elementLayout} size is greater than zero.
|
||||
* {@code elementLayout} size is greater than zero, if this segment is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the {@code elementLayout} alignment is greater than its size.
|
||||
*/
|
||||
Spliterator<MemorySegment> spliterator(MemoryLayout elementLayout);
|
||||
|
||||
@ -240,7 +292,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param elementLayout the layout to be used for splitting.
|
||||
* @return a sequential {@code Stream} over disjoint slices in this segment.
|
||||
* @throws IllegalArgumentException if the {@code elementLayout} size is zero, or the segment size modulo the
|
||||
* {@code elementLayout} size is greater than zero.
|
||||
* {@code elementLayout} size is greater than zero, if this segment is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the {@code elementLayout} alignment is greater than its size.
|
||||
*/
|
||||
Stream<MemorySegment> elements(MemoryLayout elementLayout);
|
||||
|
||||
@ -982,9 +1036,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param dstElementLayout the element layout associated with the destination segment.
|
||||
* @param dstOffset the starting offset, in bytes, of the destination segment.
|
||||
* @param elementCount the number of elements to be copied.
|
||||
* @throws IllegalArgumentException if the element layouts have different sizes, if the source offset is incompatible
|
||||
* with the alignment constraints in the source element layout, or if the destination offset is incompatible with the
|
||||
* alignment constraints in the destination element layout.
|
||||
* @throws IllegalArgumentException if the element layouts have different sizes, if the source (resp. destination) segment/offset are
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the source
|
||||
* (resp. destination) element layout, or if the source (resp. destination) element layout alignment is greater than its size.
|
||||
* @throws IllegalStateException if either the scope associated with the source segment or the scope associated
|
||||
* with the destination segment have been already closed, or if access occurs from a thread other than the thread
|
||||
* owning either scopes.
|
||||
@ -1003,13 +1057,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
|
||||
AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment;
|
||||
if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) {
|
||||
throw new IllegalArgumentException("Source and destination layouts must have same sizes");
|
||||
throw new IllegalArgumentException("Source and destination layouts must have same size");
|
||||
}
|
||||
if (srcOffset % srcElementLayout.byteAlignment() != 0) {
|
||||
Utils.checkElementAlignment(srcElementLayout, "Source layout alignment greater than its size");
|
||||
Utils.checkElementAlignment(dstElementLayout, "Destination layout alignment greater than its size");
|
||||
if (!srcImpl.isAlignedForElement(srcOffset, srcElementLayout)) {
|
||||
throw new IllegalArgumentException("Source segment incompatible with alignment constraints");
|
||||
}
|
||||
if (dstOffset % dstElementLayout.byteAlignment() != 0) {
|
||||
throw new IllegalArgumentException("Target segment incompatible with alignment constraints");
|
||||
if (!dstImpl.isAlignedForElement(dstOffset, dstElementLayout)) {
|
||||
throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
|
||||
}
|
||||
long size = elementCount * srcElementLayout.byteSize();
|
||||
srcImpl.checkAccess(srcOffset, size, true);
|
||||
@ -1034,6 +1090,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a byte value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1051,6 +1109,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the byte value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1069,6 +1129,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a boolean value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1086,6 +1148,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the boolean value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1104,6 +1168,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a char value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1121,6 +1187,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the char value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1139,6 +1207,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a short value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1156,6 +1226,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the short value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1174,6 +1246,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return an int value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1191,6 +1265,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the int value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1209,6 +1285,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a float value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1226,6 +1304,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the float value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1244,6 +1324,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a long value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1261,6 +1343,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the long value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1279,6 +1363,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a double value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1296,6 +1382,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the double value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1314,6 +1402,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return an address value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ -1331,6 +1421,8 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the address value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
@ -1349,11 +1441,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a char value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ForceInline
|
||||
default char getAtIndex(ValueLayout.OfChar layout, long index) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return (char)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -1366,12 +1462,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the char value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
*/
|
||||
@ForceInline
|
||||
default void setAtIndex(ValueLayout.OfChar layout, long index, char value) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -1384,11 +1484,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a short value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ForceInline
|
||||
default short getAtIndex(ValueLayout.OfShort layout, long index) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return (short)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -1401,12 +1505,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the short value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
*/
|
||||
@ForceInline
|
||||
default void setAtIndex(ValueLayout.OfShort layout, long index, short value) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -1419,11 +1527,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return an int value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ForceInline
|
||||
default int getAtIndex(ValueLayout.OfInt layout, long index) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return (int)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -1436,12 +1548,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the int value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
*/
|
||||
@ForceInline
|
||||
default void setAtIndex(ValueLayout.OfInt layout, long index, int value) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -1454,11 +1570,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a float value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ForceInline
|
||||
default float getAtIndex(ValueLayout.OfFloat layout, long index) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return (float)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -1471,12 +1591,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the float value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
*/
|
||||
@ForceInline
|
||||
default void setAtIndex(ValueLayout.OfFloat layout, long index, float value) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -1489,11 +1613,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a long value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ForceInline
|
||||
default long getAtIndex(ValueLayout.OfLong layout, long index) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return (long)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -1506,12 +1634,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the long value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
*/
|
||||
@ForceInline
|
||||
default void setAtIndex(ValueLayout.OfLong layout, long index, long value) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -1524,11 +1656,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return a double value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ForceInline
|
||||
default double getAtIndex(ValueLayout.OfDouble layout, long index) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return (double)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -1541,12 +1677,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the double value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
*/
|
||||
@ForceInline
|
||||
default void setAtIndex(ValueLayout.OfDouble layout, long index, double value) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -1559,11 +1699,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @return an address value read from this address.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
*/
|
||||
@ForceInline
|
||||
default MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return (MemoryAddress)layout.accessHandle().get(this, Utils.scaleOffset(this, index, layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -1576,12 +1720,16 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param value the address value to be written.
|
||||
* @throws IllegalStateException if the scope associated with this segment has been closed, or if access occurs from
|
||||
* a thread other than the thread owning that scope.
|
||||
* @throws IllegalArgumentException if the dereference operation is
|
||||
* <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the provided layout,
|
||||
* or if the layout alignment is greater than its size.
|
||||
* @throws IndexOutOfBoundsException when the dereference operation falls outside the <em>spatial bounds</em> of the
|
||||
* memory segment.
|
||||
* @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}.
|
||||
*/
|
||||
@ForceInline
|
||||
default void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value) {
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
layout.accessHandle().set(this, Utils.scaleOffset(this, index, layout.byteSize()), value.address());
|
||||
}
|
||||
|
||||
@ -1598,7 +1746,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param dstIndex the starting index of the destination array.
|
||||
* @param elementCount the number of array elements to be copied.
|
||||
* @throws IllegalArgumentException if {@code dstArray} is not an array, or if it is an array but whose type is not supported,
|
||||
* or if the destination array component type does not match the carrier of the source element layout.
|
||||
* if the destination array component type does not match the carrier of the source element layout, if the source
|
||||
* segment/offset are <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the source element layout,
|
||||
* or if the destination element layout alignment is greater than its size.
|
||||
*/
|
||||
@ForceInline
|
||||
static void copy(
|
||||
@ -1614,6 +1764,10 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
int dstBase = (int)baseAndScale;
|
||||
int dstWidth = (int)(baseAndScale >> 32);
|
||||
AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
|
||||
Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size");
|
||||
if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) {
|
||||
throw new IllegalArgumentException("Source segment incompatible with alignment constraints");
|
||||
}
|
||||
srcImpl.checkAccess(srcOffset, elementCount * dstWidth, true);
|
||||
Objects.checkFromIndexSize(dstIndex, elementCount, Array.getLength(dstArray));
|
||||
if (dstWidth == 1 || srcLayout.order() == ByteOrder.nativeOrder()) {
|
||||
@ -1639,7 +1793,9 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
* @param dstOffset the starting offset, in bytes, of the destination segment.
|
||||
* @param elementCount the number of array elements to be copied.
|
||||
* @throws IllegalArgumentException if {@code srcArray} is not an array, or if it is an array but whose type is not supported,
|
||||
* or if the source array component type does not match the carrier of the destination element layout.
|
||||
* if the source array component type does not match the carrier of the destination element layout, if the destination
|
||||
* segment/offset are <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraints</a> in the destination element layout,
|
||||
* or if the destination element layout alignment is greater than its size.
|
||||
*/
|
||||
@ForceInline
|
||||
static void copy(
|
||||
@ -1656,6 +1812,10 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory
|
||||
int srcWidth = (int)(baseAndScale >> 32);
|
||||
Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray));
|
||||
AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment;
|
||||
Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size");
|
||||
if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) {
|
||||
throw new IllegalArgumentException("Destination segment incompatible with alignment constraints");
|
||||
}
|
||||
destImpl.checkAccess(dstOffset, elementCount * srcWidth, false);
|
||||
if (srcWidth == 1 || dstLayout.order() == ByteOrder.nativeOrder()) {
|
||||
ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.scope(),
|
||||
|
@ -124,8 +124,12 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment
|
||||
if (elementLayout.byteSize() == 0) {
|
||||
throw new IllegalArgumentException("Element layout size cannot be zero");
|
||||
}
|
||||
if (byteSize() % elementLayout.byteSize() != 0) {
|
||||
throw new IllegalArgumentException("Segment size is no a multiple of layout size");
|
||||
Utils.checkElementAlignment(elementLayout, "Element layout alignment greater than its size");
|
||||
if (!isAlignedForElement(0, elementLayout)) {
|
||||
throw new IllegalArgumentException("Incompatible alignment constraints");
|
||||
}
|
||||
if (!Utils.isAligned(byteSize(), elementLayout.byteSize())) {
|
||||
throw new IllegalArgumentException("Segment size is not a multiple of layout size");
|
||||
}
|
||||
return new SegmentSplitter(elementLayout.byteSize(), byteSize() / elementLayout.byteSize(),
|
||||
this);
|
||||
@ -383,8 +387,13 @@ public abstract non-sealed class AbstractMemorySegmentImpl extends MemorySegment
|
||||
return (this.mask & mask) != 0;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public final boolean isAlignedForElement(long offset, MemoryLayout layout) {
|
||||
return (((unsafeGetOffset() + offset) | maxAlignMask()) & (layout.byteAlignment() - 1)) == 0;
|
||||
}
|
||||
|
||||
private int checkArraySize(String typeName, int elemSize) {
|
||||
if (length % elemSize != 0) {
|
||||
if (!Utils.isAligned(length, elemSize)) {
|
||||
throw new IllegalStateException(String.format("Segment size is not a multiple of %d. Size: %d", elemSize, length));
|
||||
}
|
||||
long arraySize = length / elemSize;
|
||||
|
@ -47,6 +47,11 @@ public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
private static final int BYTE_ARR_BASE = UNSAFE.arrayBaseOffset(byte[].class);
|
||||
|
||||
private static final long MAX_ALIGN_1 = 1;
|
||||
private static final long MAX_ALIGN_2 = 2;
|
||||
private static final long MAX_ALIGN_4 = 4;
|
||||
private static final long MAX_ALIGN_8 = 8;
|
||||
|
||||
final long offset;
|
||||
final H base;
|
||||
|
||||
@ -100,6 +105,11 @@ public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_BYTE_INDEX_SCALE;
|
||||
return new OfByte(Unsafe.ARRAY_BYTE_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_1;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OfChar extends HeapMemorySegmentImpl<char[]> {
|
||||
@ -123,6 +133,11 @@ public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_CHAR_INDEX_SCALE;
|
||||
return new OfChar(Unsafe.ARRAY_CHAR_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_2;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OfShort extends HeapMemorySegmentImpl<short[]> {
|
||||
@ -146,6 +161,11 @@ public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_SHORT_INDEX_SCALE;
|
||||
return new OfShort(Unsafe.ARRAY_SHORT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_2;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OfInt extends HeapMemorySegmentImpl<int[]> {
|
||||
@ -169,6 +189,11 @@ public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_INT_INDEX_SCALE;
|
||||
return new OfInt(Unsafe.ARRAY_INT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_4;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OfLong extends HeapMemorySegmentImpl<long[]> {
|
||||
@ -192,6 +217,11 @@ public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_LONG_INDEX_SCALE;
|
||||
return new OfLong(Unsafe.ARRAY_LONG_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_8;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OfFloat extends HeapMemorySegmentImpl<float[]> {
|
||||
@ -215,6 +245,11 @@ public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_FLOAT_INDEX_SCALE;
|
||||
return new OfFloat(Unsafe.ARRAY_FLOAT_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_4;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OfDouble extends HeapMemorySegmentImpl<double[]> {
|
||||
@ -238,6 +273,11 @@ public abstract class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl
|
||||
long byteSize = (long)arr.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE;
|
||||
return new OfDouble(Unsafe.ARRAY_DOUBLE_BASE_OFFSET, arr, byteSize, defaultAccessModes(byteSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return MAX_ALIGN_8;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -282,11 +282,11 @@ public class LayoutPath {
|
||||
private static void checkAlignment(LayoutPath path) {
|
||||
MemoryLayout layout = path.layout;
|
||||
long alignment = layout.bitAlignment();
|
||||
if (path.offset % alignment != 0) {
|
||||
if (!Utils.isAligned(path.offset, alignment)) {
|
||||
throw new UnsupportedOperationException("Invalid alignment requirements for layout " + layout);
|
||||
}
|
||||
for (long stride : path.strides) {
|
||||
if (stride % alignment != 0) {
|
||||
if (!Utils.isAligned(stride, alignment)) {
|
||||
throw new UnsupportedOperationException("Alignment requirements for layout " + layout + " do not match stride " + stride);
|
||||
}
|
||||
}
|
||||
|
@ -267,6 +267,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public char getAtIndex(ValueLayout.OfChar layout, long index) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -275,6 +276,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public void setAtIndex(ValueLayout.OfChar layout, long index, char value) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -283,6 +285,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public short getAtIndex(ValueLayout.OfShort layout, long index) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -291,6 +294,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public void setAtIndex(ValueLayout.OfShort layout, long index, short value) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -299,6 +303,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public int getAtIndex(ValueLayout.OfInt layout, long index) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -307,6 +312,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public void setAtIndex(ValueLayout.OfInt layout, long index, int value) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -315,6 +321,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public float getAtIndex(ValueLayout.OfFloat layout, long index) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -323,6 +330,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public void setAtIndex(ValueLayout.OfFloat layout, long index, float value) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -331,6 +339,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public long getAtIndex(ValueLayout.OfLong layout, long index) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -339,6 +348,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public void setAtIndex(ValueLayout.OfLong layout, long index, long value) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -347,6 +357,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public double getAtIndex(ValueLayout.OfDouble layout, long index) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -355,6 +366,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public void setAtIndex(ValueLayout.OfDouble layout, long index, double value) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value);
|
||||
}
|
||||
|
||||
@ -363,6 +375,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize()));
|
||||
}
|
||||
|
||||
@ -371,6 +384,7 @@ public final class MemoryAddressImpl implements MemoryAddress, Scoped {
|
||||
@CallerSensitive
|
||||
public void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass());
|
||||
Utils.checkElementAlignment(layout, "Layout alignment greater than its size");
|
||||
NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value.address());
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +92,11 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxAlignMask() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// factories
|
||||
|
||||
public static MemorySegment makeNativeSegment(long bytesSize, long alignmentBytes, ResourceScopeImpl scope) {
|
||||
|
@ -98,7 +98,7 @@ public final class Utils {
|
||||
}
|
||||
|
||||
public static long bitsToBytesOrThrow(long bits, Supplier<RuntimeException> exFactory) {
|
||||
if (bits % 8 == 0) {
|
||||
if (Utils.isAligned(bits, 8)) {
|
||||
return bits / 8;
|
||||
} else {
|
||||
throw exFactory.get();
|
||||
@ -173,4 +173,16 @@ public final class Utils {
|
||||
// note: we know size is a small value (as it comes from ValueLayout::byteSize())
|
||||
return MemorySegmentProxy.multiplyOffsets(index, (int)size, (AbstractMemorySegmentImpl)segment);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static boolean isAligned(long offset, long align) {
|
||||
return (offset & (align - 1)) == 0;
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public static void checkElementAlignment(MemoryLayout layout, String msg) {
|
||||
if (layout.byteAlignment() > layout.byteSize()) {
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -253,6 +253,18 @@ public class TestArrayCopy {
|
||||
MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_INT, 0, 4);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testHyperAlignedSrc() {
|
||||
MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
MemorySegment.copy(new byte[] { 1, 2, 3, 4 }, 0, segment, JAVA_BYTE.withBitAlignment(16), 0, 4);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testHyperAlignedDst() {
|
||||
MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
MemorySegment.copy(segment, JAVA_BYTE.withBitAlignment(16), 0, new byte[] { 1, 2, 3, 4 }, 0, 4);
|
||||
}
|
||||
|
||||
/***** Utilities *****/
|
||||
|
||||
public static MemorySegment srcSegment(int bytesLength) {
|
||||
|
131
test/jdk/java/foreign/TestHeapAlignment.java
Normal file
131
test/jdk/java/foreign/TestHeapAlignment.java
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
|
||||
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestHeapAlignment
|
||||
*/
|
||||
|
||||
import jdk.incubator.foreign.MemoryAddress;
|
||||
import jdk.incubator.foreign.MemoryLayout;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
import jdk.incubator.foreign.ValueLayout;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
public class TestHeapAlignment {
|
||||
|
||||
@Test(dataProvider = "layouts")
|
||||
public void testHeapAlignment(MemorySegment segment, int align, Object val, Object arr, ValueLayout layout, Function<Object, MemorySegment> segmentFactory) {
|
||||
assertAligned(align, layout, () -> layout.varHandle().get(segment));
|
||||
assertAligned(align, layout, () -> layout.varHandle().set(segment, val));
|
||||
MemoryLayout seq = MemoryLayout.sequenceLayout(10, layout);
|
||||
assertAligned(align, layout, () -> seq.varHandle(MemoryLayout.PathElement.sequenceElement()).get(segment, 0L));
|
||||
assertAligned(align, layout, () -> seq.varHandle(MemoryLayout.PathElement.sequenceElement()).set(segment, 0L, val));
|
||||
assertAligned(align, layout, () -> segment.spliterator(layout));
|
||||
if (arr != null) {
|
||||
assertAligned(align, layout, () -> MemorySegment.copy(arr, 0, segment, layout, 0, 1));
|
||||
assertAligned(align, layout, () -> MemorySegment.copy(segment, layout, 0, arr, 0, 1));
|
||||
assertAligned(align, layout, () -> {
|
||||
MemorySegment other = segmentFactory.apply(arr);
|
||||
MemorySegment.copy(other, layout, 0, segment, layout, 0, 1);
|
||||
});
|
||||
MemorySegment other = segmentFactory.apply(arr);
|
||||
assertAligned(align, layout, () -> {
|
||||
MemorySegment.copy(segment, layout, 0, other, layout, 0, 1);
|
||||
});
|
||||
assertAligned(align, layout, () -> {
|
||||
MemorySegment.copy(other, layout, 0, segment, layout, 0, 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void assertAligned(int align, ValueLayout layout, Runnable runnable) {
|
||||
boolean shouldFail = layout.byteAlignment() > align && align != -1;
|
||||
try {
|
||||
runnable.run();
|
||||
if (shouldFail) {
|
||||
fail("Should not get here!");
|
||||
}
|
||||
} catch (IllegalArgumentException ex) {
|
||||
if (!shouldFail) {
|
||||
fail("Should not get here!");
|
||||
} else if (!ex.getMessage().contains("alignment") && !ex.getMessage().contains("Misaligned")) {
|
||||
fail("Unexpected exception: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final ValueLayout.OfChar JAVA_CHAR_ALIGNED = ValueLayout.JAVA_CHAR.withBitAlignment(16);
|
||||
static final ValueLayout.OfShort JAVA_SHORT_ALIGNED = ValueLayout.JAVA_SHORT.withBitAlignment(16);
|
||||
static final ValueLayout.OfInt JAVA_INT_ALIGNED = ValueLayout.JAVA_INT.withBitAlignment(32);
|
||||
static final ValueLayout.OfFloat JAVA_FLOAT_ALIGNED = ValueLayout.JAVA_FLOAT.withBitAlignment(32);
|
||||
static final ValueLayout.OfLong JAVA_LONG_ALIGNED = ValueLayout.JAVA_LONG.withBitAlignment(64);
|
||||
static final ValueLayout.OfDouble JAVA_DOUBLE_ALIGNED = ValueLayout.JAVA_DOUBLE.withBitAlignment(64);
|
||||
static final ValueLayout.OfAddress ADDRESS_ALIGNED = ValueLayout.ADDRESS.withBitAlignment(ValueLayout.ADDRESS.bitSize());
|
||||
|
||||
enum SegmentAndAlignment {
|
||||
HEAP_BYTE(MemorySegment.ofArray(new byte[8]), 1),
|
||||
HEAP_SHORT(MemorySegment.ofArray(new short[4]), 2),
|
||||
HEAP_CHAR(MemorySegment.ofArray(new char[4]), 2),
|
||||
HEAP_INT(MemorySegment.ofArray(new int[2]), 4),
|
||||
HEAP_FLOAT(MemorySegment.ofArray(new float[2]), 4),
|
||||
HEAP_LONG(MemorySegment.ofArray(new long[1]), 8),
|
||||
HEAP_DOUBLE(MemorySegment.ofArray(new double[1]), 8),
|
||||
NATIVE(MemorySegment.allocateNative(8, ResourceScope.newImplicitScope()), -1);
|
||||
|
||||
final MemorySegment segment;
|
||||
final int align;
|
||||
|
||||
SegmentAndAlignment(MemorySegment segment, int align) {
|
||||
this.segment = segment;
|
||||
this.align = align;
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider
|
||||
public static Object[][] layouts() {
|
||||
List<Object[]> layouts = new ArrayList<>();
|
||||
for (SegmentAndAlignment testCase : SegmentAndAlignment.values()) {
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, (byte) 42, new byte[]{42}, ValueLayout.JAVA_BYTE, (Function<byte[], MemorySegment>)MemorySegment::ofArray });
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, true, null, ValueLayout.JAVA_BOOLEAN, null });
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, (char) 42, new char[]{42}, JAVA_CHAR_ALIGNED, (Function<char[], MemorySegment>)MemorySegment::ofArray });
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, (short) 42, new short[]{42}, JAVA_SHORT_ALIGNED, (Function<short[], MemorySegment>)MemorySegment::ofArray });
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, 42, new int[]{42}, JAVA_INT_ALIGNED, (Function<int[], MemorySegment>)MemorySegment::ofArray });
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, 42f, new float[]{42}, JAVA_FLOAT_ALIGNED, (Function<float[], MemorySegment>)MemorySegment::ofArray });
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, 42L, new long[]{42}, JAVA_LONG_ALIGNED, (Function<long[], MemorySegment>)MemorySegment::ofArray });
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, 42d, new double[]{42}, JAVA_DOUBLE_ALIGNED, (Function<double[], MemorySegment>)MemorySegment::ofArray });
|
||||
layouts.add(new Object[] { testCase.segment, testCase.align, MemoryAddress.ofLong(42), null, ADDRESS_ALIGNED, null });
|
||||
}
|
||||
return layouts.toArray(new Object[0][]);
|
||||
}
|
||||
}
|
@ -35,12 +35,13 @@ import java.util.function.Function;
|
||||
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
import jdk.incubator.foreign.ValueLayout;
|
||||
import org.testng.SkipException;
|
||||
import org.testng.annotations.*;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class TestMemoryAccessInstance {
|
||||
|
||||
static class Accessor<T, X, L> {
|
||||
static class Accessor<T, X, L extends ValueLayout> {
|
||||
|
||||
interface SegmentGetter<T, X, L> {
|
||||
X get(T buffer, L layout, long offset);
|
||||
@ -90,13 +91,34 @@ public class TestMemoryAccessInstance {
|
||||
}
|
||||
}
|
||||
|
||||
static <L, X> Accessor<MemorySegment, X, L> ofSegment(L layout, X value,
|
||||
@SuppressWarnings("unchecked")
|
||||
void testHyperAligned() {
|
||||
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
|
||||
MemorySegment segment = MemorySegment.allocateNative(64, scope);
|
||||
T t = transform.apply(segment);
|
||||
L alignedLayout = (L)layout.withBitAlignment(layout.byteSize() * 8 * 2);
|
||||
try {
|
||||
segmentSetter.set(t, alignedLayout, 0, value);
|
||||
fail();
|
||||
} catch (IllegalArgumentException exception) {
|
||||
assertTrue(exception.getMessage().contains("greater"));
|
||||
}
|
||||
try {
|
||||
segmentGetter.get(t, alignedLayout, 0);
|
||||
fail();
|
||||
} catch (IllegalArgumentException exception) {
|
||||
assertTrue(exception.getMessage().contains("greater"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static <L extends ValueLayout, X> Accessor<MemorySegment, X, L> ofSegment(L layout, X value,
|
||||
SegmentGetter<MemorySegment, X, L> segmentGetter, SegmentSetter<MemorySegment, X, L> segmentSetter,
|
||||
BufferGetter<X> bufferGetter, BufferSetter<X> bufferSetter) {
|
||||
return new Accessor<>(Function.identity(), layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter);
|
||||
}
|
||||
|
||||
static <L, X> Accessor<MemoryAddress, X, L> ofAddress(L layout, X value,
|
||||
static <L extends ValueLayout, X> Accessor<MemoryAddress, X, L> ofAddress(L layout, X value,
|
||||
SegmentGetter<MemoryAddress, X, L> segmentGetter, SegmentSetter<MemoryAddress, X, L> segmentSetter,
|
||||
BufferGetter<X> bufferGetter, BufferSetter<X> bufferSetter) {
|
||||
return new Accessor<>(MemorySegment::address, layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter);
|
||||
@ -113,6 +135,24 @@ public class TestMemoryAccessInstance {
|
||||
accessor.test();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "segmentAccessors")
|
||||
public void testSegmentAccessHyper(String testName, Accessor<?, ?, ?> accessor) {
|
||||
if (testName.contains("index")) {
|
||||
accessor.testHyperAligned();
|
||||
} else {
|
||||
throw new SkipException("Skipping");
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "addressAccessors")
|
||||
public void testAddressAccessHyper(String testName, Accessor<?, ?, ?> accessor) {
|
||||
if (testName.contains("index")) {
|
||||
accessor.testHyperAligned();
|
||||
} else {
|
||||
throw new SkipException("Skipping");
|
||||
}
|
||||
}
|
||||
|
||||
static final ByteOrder NE = ByteOrder.nativeOrder();
|
||||
|
||||
@DataProvider(name = "segmentAccessors")
|
||||
|
@ -74,7 +74,7 @@ public class TestMemoryAlignment {
|
||||
MemorySegment segment = MemorySegment.allocateNative(alignedGroup, scope);
|
||||
vh.set(segment.asSlice(1L), -42);
|
||||
assertEquals(align, 8); //this is the only case where access is aligned
|
||||
} catch (IllegalStateException ex) {
|
||||
} catch (IllegalArgumentException ex) {
|
||||
assertNotEquals(align, 8); //if align != 8, access is always unaligned
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
import static jdk.incubator.foreign.ValueLayout.JAVA_BYTE;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class TestSegmentCopy {
|
||||
@ -81,12 +82,16 @@ public class TestSegmentCopy {
|
||||
}
|
||||
}
|
||||
|
||||
interface Getter<X> {
|
||||
X get(MemorySegment segment, ValueLayout layout, long index);
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testHyperAlignedSrc() {
|
||||
MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
MemorySegment.copy(segment, 0, segment, JAVA_BYTE.withBitAlignment(16), 0, 4);
|
||||
}
|
||||
|
||||
interface Setter<X> {
|
||||
void set(MemorySegment segment, ValueLayout layout, long index, X val);
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testHyperAlignedDst() {
|
||||
MemorySegment segment = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
|
||||
MemorySegment.copy(segment, JAVA_BYTE.withBitAlignment(16), 0, segment, 0, 4);
|
||||
}
|
||||
|
||||
enum Type {
|
||||
|
@ -127,6 +127,11 @@ public class TestSpliterator {
|
||||
MemorySegment.ofArray(new byte[7]).elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testHyperAligned() {
|
||||
MemorySegment.ofArray(new byte[8]).elements(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT.withBitAlignment(64)));
|
||||
}
|
||||
|
||||
static long sumSingle(long acc, MemorySegment segment) {
|
||||
return acc + (int)INT_HANDLE.get(segment, 0L);
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class TestVarHandleCombinators {
|
||||
assertEquals((byte) vh.get(segment, 2), (byte) -1);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class)
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testUnalignedElement() {
|
||||
VarHandle vh = MemoryHandles.varHandle(ValueLayout.JAVA_BYTE.withBitAlignment(32));
|
||||
MemorySegment segment = MemorySegment.ofArray(new byte[4]);
|
||||
|
@ -26,6 +26,7 @@ import jdk.incubator.foreign.MemoryAddress;
|
||||
import jdk.incubator.foreign.MemoryLayout;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
import jdk.incubator.foreign.ValueLayout;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
@ -61,6 +62,10 @@ public class LoopOverNonConstant {
|
||||
static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE;
|
||||
|
||||
static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement());
|
||||
|
||||
static final ValueLayout.OfInt JAVA_INT_ALIGNED = JAVA_INT.withBitAlignment(32);
|
||||
static final VarHandle VH_int_aligned = MemoryLayout.sequenceLayout(JAVA_INT_ALIGNED).varHandle(sequenceElement());
|
||||
|
||||
MemorySegment segment;
|
||||
long unsafe_addr;
|
||||
|
||||
@ -125,6 +130,15 @@ public class LoopOverNonConstant {
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int segment_loop_aligned() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < ELEM_SIZE; i++) {
|
||||
sum += (int) VH_int_aligned.get(segment, (long) i);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int segment_loop_instance() {
|
||||
int sum = 0;
|
||||
@ -145,6 +159,15 @@ public class LoopOverNonConstant {
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int segment_loop_instance_aligned() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < ELEM_SIZE; i ++) {
|
||||
res += segment.get(JAVA_INT_ALIGNED, i * CARRIER_SIZE);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int segment_loop_instance_address() {
|
||||
int sum = 0;
|
||||
|
@ -25,6 +25,7 @@ package org.openjdk.bench.jdk.incubator.foreign;
|
||||
import jdk.incubator.foreign.MemoryLayout;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
import jdk.incubator.foreign.ValueLayout;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
@ -66,8 +67,14 @@ public class LoopOverNonConstantHeap {
|
||||
static final int UNSAFE_BYTE_BASE = unsafe.arrayBaseOffset(byte[].class);
|
||||
|
||||
static final VarHandle VH_int = MemoryLayout.sequenceLayout(JAVA_INT).varHandle(sequenceElement());
|
||||
MemorySegment segment;
|
||||
|
||||
static final ValueLayout.OfInt JAVA_INT_ALIGNED = JAVA_INT.withBitAlignment(32);
|
||||
static final VarHandle VH_int_aligned = MemoryLayout.sequenceLayout(JAVA_INT_ALIGNED).varHandle(sequenceElement());
|
||||
static final int UNSAFE_INT_BASE = unsafe.arrayBaseOffset(int[].class);
|
||||
|
||||
MemorySegment segment, alignedSegment;
|
||||
byte[] base;
|
||||
int[] alignedBase;
|
||||
|
||||
ByteBuffer byteBuffer;
|
||||
|
||||
@ -95,7 +102,12 @@ public class LoopOverNonConstantHeap {
|
||||
for (int i = 0; i < ELEM_SIZE; i++) {
|
||||
unsafe.putInt(base, UNSAFE_BYTE_BASE + (i * CARRIER_SIZE) , i);
|
||||
}
|
||||
alignedBase = new int[ELEM_SIZE];
|
||||
for (int i = 0; i < ELEM_SIZE; i++) {
|
||||
unsafe.putInt(base, UNSAFE_INT_BASE + (i * CARRIER_SIZE) , i);
|
||||
}
|
||||
segment = MemorySegment.ofArray(base);
|
||||
alignedSegment = MemorySegment.ofArray(alignedBase);
|
||||
byteBuffer = ByteBuffer.wrap(base).order(ByteOrder.nativeOrder());
|
||||
}
|
||||
|
||||
@ -135,6 +147,15 @@ public class LoopOverNonConstantHeap {
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int segment_loop_aligned() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < ELEM_SIZE; i++) {
|
||||
sum += (int) VH_int_aligned.get(alignedSegment, (long) i);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int segment_loop_instance() {
|
||||
int res = 0;
|
||||
@ -144,6 +165,15 @@ public class LoopOverNonConstantHeap {
|
||||
return res;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int segment_loop_instance_aligned() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < ELEM_SIZE; i ++) {
|
||||
res += alignedSegment.get(JAVA_INT_ALIGNED, i * CARRIER_SIZE);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public int segment_loop_slice() {
|
||||
int sum = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user