8308248: Revisit alignment of layout constants on 32-bit platforms

Reviewed-by: psandoz, pminborg
This commit is contained in:
Maurizio Cimadamore 2023-05-19 14:28:14 +00:00
parent 80ef5c228b
commit 44218b1c9e
6 changed files with 62 additions and 39 deletions

View file

@ -264,12 +264,6 @@ import jdk.internal.vm.annotation.ForceInline;
* collection. Access operations rely on this invariant to determine if the specified offset in a heap segment refers
* to an aligned address in physical memory. For example:
* <ul>
* <li>The starting physical address of a {@code long[]} array will be 8-byte aligned (e.g. 1000), so that successive long elements
* occur at 8-byte aligned addresses (e.g., 1000, 1008, 1016, 1024, etc.) A heap segment backed by a {@code long[]} array
* can be accessed at offsets 0, 8, 16, 24, etc under an 8-byte alignment constraint. In addition, the segment can be
* accessed at offsets 0, 4, 8, 12, etc under a 4-byte alignment constraint, because the target addresses
* (1000, 1004, 1008, 1012) are 4-byte aligned. And, the segment can be accessed at offsets 0, 2, 4, 6, etc under a
* 2-byte alignment constraint, because the target addresses (e.g. 1000, 1002, 1004, 1006) are 2-byte aligned.</li>
* <li>The starting physical address of a {@code short[]} array will be 2-byte aligned (e.g. 1006) so that successive
* short elements occur at 2-byte aligned addresses (e.g. 1006, 1008, 1010, 1012, etc). A heap segment backed by a
* {@code short[]} array can be accessed at offsets 0, 2, 4, 6, etc under a 2-byte alignment constraint. The segment cannot
@ -278,10 +272,22 @@ import jdk.internal.vm.annotation.ForceInline;
* to physical address 1007. Similarly, the segment cannot be accessed at any offset under an 8-byte alignment constraint,
* because because there is no guarantee that the target address would be 8-byte aligned, e.g., offset 2 would correspond
* to physical address 1008 but offset 4 would correspond to physical address 1010.</li>
* <li>The starting physical address of a {@code long[]} array will be 8-byte aligned (e.g. 1000) on 64-bit platforms,
* so that successive long elements occur at 8-byte aligned addresses (e.g., 1000, 1008, 1016, 1024, etc.) On 64-bit platforms,
* a heap segment backed by a {@code long[]} array can be accessed at offsets 0, 8, 16, 24, etc under an 8-byte alignment
* constraint. In addition, the segment can be accessed at offsets 0, 4, 8, 12, etc under a 4-byte alignment constraint,
* because the target addresses (1000, 1004, 1008, 1012) are 4-byte aligned. And, the segment can be accessed at offsets
* 0, 2, 4, 6, etc under a 2-byte alignment constraint, because the target addresses (e.g. 1000, 1002, 1004, 1006) are 2-byte aligned.</li>
* <li>The starting physical address of a {@code long[]} array will be 4-byte aligned (e.g. 1000) on 32-bit platforms,
* so that successive long elements occur at 4-byte aligned addresses (e.g., 1004, 1008, 1012, 1016, etc.) On 32-bit
* platforms, a heap segment backed by a {@code long[]} array can be accessed at offsets 0, 4, 8, 12, etc under a 4-byte
* alignment constraint, because the target addresses (1000, 1004, 1008, 1012) are 4-byte aligned. And, the segment
* can be accessed at offsets 0, 2, 4, 6, etc under a 2-byte alignment constraint, because the target addresses
* (e.g. 1000, 1002, 1004, 1006) are 2-byte aligned.</li>
* </ul>
* <p>
* In other words, heap segments feature a <em>maximum</em> alignment which is derived from the size of the elements of
* the Java array backing the segment, as shown in the following table:
* In other words, heap segments feature a (platform-dependent) <em>maximum</em> alignment which is derived from the
* size of the elements of the Java array backing the segment, as shown in the following table:
*
* <blockquote><table class="plain">
* <caption style="display:none">Maximum alignment of heap segments</caption>
@ -293,21 +299,21 @@ import jdk.internal.vm.annotation.ForceInline;
* </thead>
* <tbody>
* <tr><th scope="row" style="font-weight:normal">{@code boolean[]}</th>
* <td style="text-align:center;">{@code 1}</td></tr>
* <td style="text-align:center;">{@code ValueLayout.JAVA_BOOLEAN.byteAlignment()}</td></tr>
* <tr><th scope="row" style="font-weight:normal">{@code byte[]}</th>
* <td style="text-align:center;">{@code 1}</td></tr>
* <td style="text-align:center;">{@code ValueLayout.JAVA_BYTE.byteAlignment()}</td></tr>
* <tr><th scope="row" style="font-weight:normal">{@code char[]}</th>
* <td style="text-align:center;">{@code 2}</td></tr>
* <td style="text-align:center;">{@code ValueLayout.JAVA_CHAR.byteAlignment()}</td></tr>
* <tr><th scope="row" style="font-weight:normal">{@code short[]}</th>
* <td style="text-align:center;">{@code 2}</td></tr>
* <td style="text-align:center;">{@code ValueLayout.JAVA_SHORT.byteAlignment()}</td></tr>
* <tr><th scope="row" style="font-weight:normal">{@code int[]}</th>
* <td style="text-align:center;">{@code 4}</td></tr>
* <td style="text-align:center;">{@code ValueLayout.JAVA_INT.byteAlignment()}</td></tr>
* <tr><th scope="row" style="font-weight:normal">{@code float[]}</th>
* <td style="text-align:center;">{@code 4}</td></tr>
* <td style="text-align:center;">{@code ValueLayout.JAVA_FLOAT.byteAlignment()}</td></tr>
* <tr><th scope="row" style="font-weight:normal">{@code long[]}</th>
* <td style="text-align:center;">{@code 8}</td></tr>
* <td style="text-align:center;">{@code ValueLayout.JAVA_LONG.byteAlignment()}</td></tr>
* <tr><th scope="row" style="font-weight:normal">{@code double[]}</th>
* <td style="text-align:center;">{@code 8}</td></tr>
* <td style="text-align:center;">{@code ValueLayout.JAVA_DOUBLE.byteAlignment()}</td></tr>
* </tbody>
* </table></blockquote>
*
@ -318,22 +324,25 @@ import jdk.internal.vm.annotation.ForceInline;
*
* {@snippet lang=java :
* MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
* byteSegment.get(ValueLayout.JAVA_INT, 0); // fails: layout alignment is 4, segment max alignment is 1
* byteSegment.get(ValueLayout.JAVA_INT, 0); // fails: ValueLayout.JAVA_INT.byteAlignment() > ValueLayout.JAVA_BYTE.byteAlignment()
* }
*
* In such circumstances, clients have two options. They can use a heap segment backed by a different array
* type (e.g. {@code long[]}), capable of supporting greater maximum alignment:
* type (e.g. {@code long[]}), capable of supporting greater maximum alignment. More specifically, the maximum alignment
* associated with {@code long[]} is set to {@code ValueLayout.JAVA_LONG.byteAlignment()} which is a platform-dependent
* value (set to {@code ValueLayout.ADDRESS.byteSize()}). That is, {@code long[]}) is guaranteed to provide at least
* 8-byte alignment in 64-bit platforms, but only 4-byte alignment in 32-bit platforms:
*
* {@snippet lang=java :
* MemorySegment longSegment = MemorySegment.ofArray(new long[10]);
* longSegment.get(ValueLayout.JAVA_INT, 0); // ok: layout alignment is 4, segment max alignment is 8
* longSegment.get(ValueLayout.JAVA_INT, 0); // ok: ValueLayout.JAVA_INT.byteAlignment() <= ValueLayout.JAVA_LONG.byteAlignment()
* }
*
* Alternatively, they can invoke the access operation with an <em>unaligned layout</em>.
* All unaligned layout constants (e.g. {@link ValueLayout#JAVA_INT_UNALIGNED}) have their alignment constraint set to 1:
* {@snippet lang=java :
* MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
* byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, 0); // ok: layout alignment is 1, segment max alignment is 1
* byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, 0); // ok: ValueLayout.JAVA_INT_UNALIGNED.byteAlignment() == ValueLayout.JAVA_BYTE.byteAlignment()
* }
*
* <h2 id="wrapping-addresses">Zero-length memory segments</h2>

View file

@ -485,7 +485,8 @@ public sealed interface ValueLayout extends MemoryLayout permits
/**
* A value layout constant whose size is the same as that of a Java {@code long},
* bit alignment set to 64, and byte order set to {@link ByteOrder#nativeOrder()}.
* (platform-dependent) bit alignment set to {@code ADDRESS.bitSize()},
* and byte order set to {@link ByteOrder#nativeOrder()}.
*/
OfLong JAVA_LONG = ValueLayouts.OfLongImpl.of(ByteOrder.nativeOrder());
@ -497,7 +498,8 @@ public sealed interface ValueLayout extends MemoryLayout permits
/**
* A value layout constant whose size is the same as that of a Java {@code double},
* bit alignment set to 64, and byte order set to {@link ByteOrder#nativeOrder()}.
* (platform-dependent) bit alignment set to {@code ADDRESS.bitSize()},
* and byte order set to {@link ByteOrder#nativeOrder()}.
*/
OfDouble JAVA_DOUBLE = ValueLayouts.OfDoubleImpl.of(ByteOrder.nativeOrder());