< prev index next >
src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/MemoryHandles.java
Print this page
@@ -79,18 +79,14 @@
* <em>static</em> constants which are can be acquired through the {@link MemoryHandles#withOffset(VarHandle, long)}
* and the {@link MemoryHandles#withStride(VarHandle, long)} combinators, respectively.
*
* <h2><a id="memaccess-mode"></a>Alignment and access modes</h2>
*
- * Memory access may be <em>aligned</em> or <em>misaligned</em> for the given carrier {@code T},
- * with respect to the underlying memory address, {@code A} say, which is the final address (computed by the formula described above)
- * at which the memory dereference operation occurs.
- *
- * If access is misaligned then access for anything other than the {@code get} and {@code set} access modes will result
- * in an {@code IllegalStateException}. In such cases atomic access is only guaranteed with respect to the largest power
- * of two that divides the GCD of {@code A} and the size (in bytes) of {@code T}.
- * If access is aligned then following access modes are supported and are
+ * A memory access var handle is associated with an access size {@code S} and an alignment constraint {@code B}
+ * (both expressed in bytes). We say that a memory access operation is <em>fully aligned</em> if it occurs
+ * at a memory address {@code A} which is compatible with both alignment constraints {@code S} and {@code B}.
+ * If access is fully aligned then following access modes are supported and are
* guaranteed to support atomic access:
* <ul>
* <li>read write access modes for all {@code T}, with the exception of
* access modes {@code get} and {@code set} for {@code long} and
* {@code double} on 32-bit platforms.
@@ -103,15 +99,23 @@
* numeric types for certain currently unsupported access modes.)
* <li>bitwise atomic update access modes for {@code int} and {@code long}.
* (Future major platform releases of the JDK may support additional
* numeric types for certain currently unsupported access modes.)
* </ul>
- * <p>
+ *
* If {@code T} is {@code float} or {@code double} then atomic
* update access modes compare values using their bitwise representation
* (see {@link Float#floatToRawIntBits} and
* {@link Double#doubleToRawLongBits}, respectively).
+ * <p>
+ * Alternatively, a memory access operation is <em>partially aligned</em> if it occurs at a memory address {@code A}
+ * which is only compatible with the alignment constraint {@code B}; in such cases, access for anything other than the
+ * {@code get} and {@code set} access modes will result in an {@code IllegalStateException}. If access is partially aligned,
+ * atomic access is only guaranteed with respect to the largest power of two that divides the GCD of {@code A} and {@code S}.
+ * <p>
+ * Finally, in all other cases, we say that a memory access operation is <em>misaligned</em>; in such cases an
+ * {@code IllegalStateException} is thrown, irrespective of the access mode being used.
*/
public final class MemoryHandles {
private final static JavaLangInvokeAccess JLI = SharedSecrets.getJavaLangInvokeAccess();
@@ -168,11 +172,11 @@
if (alignmentBytes <= 0
|| (alignmentBytes & (alignmentBytes - 1)) != 0) { // is power of 2?
throw new IllegalArgumentException("Bad alignment: " + alignmentBytes);
}
- return JLI.memoryAddressViewVarHandle(carrier, alignmentBytes, byteOrder, 0, new long[]{});
+ return JLI.memoryAddressViewVarHandle(carrier, alignmentBytes - 1, byteOrder, 0, new long[]{});
}
/**
* Creates a memory access var handle with a fixed offset added to the accessed offset. That is,
* if the target memory access var handle accesses a memory location at offset <em>O</em>, the new memory access var
@@ -192,19 +196,19 @@
public static VarHandle withOffset(VarHandle target, long bytesOffset) {
if (bytesOffset < 0) {
throw new IllegalArgumentException("Illegal offset: " + bytesOffset);
}
- long align = JLI.memoryAddressAlignment(target);
+ long alignMask = JLI.memoryAddressAlignmentMask(target);
- if (bytesOffset % align != 0) {
- throw new IllegalArgumentException("Offset " + bytesOffset + " does not conform to alignment " + align);
+ if ((bytesOffset & alignMask) != 0) {
+ throw new IllegalArgumentException("Offset " + bytesOffset + " does not conform to alignment " + (alignMask + 1));
}
return JLI.memoryAddressViewVarHandle(
JLI.memoryAddressCarrier(target),
- align,
+ alignMask,
JLI.memoryAddressByteOrder(target),
JLI.memoryAddressOffset(target) + bytesOffset,
JLI.memoryAddressStrides(target));
}
@@ -228,27 +232,26 @@
public static VarHandle withStride(VarHandle target, long bytesStride) {
if (bytesStride == 0) {
throw new IllegalArgumentException("Stride must be positive: " + bytesStride);
}
- long align = JLI.memoryAddressAlignment(target);
+ long alignMask = JLI.memoryAddressAlignmentMask(target);
- if (bytesStride % align != 0) {
- throw new IllegalArgumentException("Stride " + bytesStride + " does not conform to alignment " + align);
+ if ((bytesStride & alignMask) != 0) {
+ throw new IllegalArgumentException("Stride " + bytesStride + " does not conform to alignment " + (alignMask + 1));
}
long offset = JLI.memoryAddressOffset(target);
- Class<?> carrier = JLI.memoryAddressCarrier(target);
long[] strides = JLI.memoryAddressStrides(target);
long[] newStrides = new long[strides.length + 1];
System.arraycopy(strides, 0, newStrides, 1, strides.length);
newStrides[0] = bytesStride;
return JLI.memoryAddressViewVarHandle(
JLI.memoryAddressCarrier(target),
- align,
+ alignMask,
JLI.memoryAddressByteOrder(target),
offset,
newStrides);
}
< prev index next >