Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8330338

Add provisions for checking memory segment alignment constraints

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 23
    • core-libs
    • None
    • source
    • minimal
    • Hide
      The interface `MemorySegment` is sealed and only permits internal implementations. Consequently, there could be no overriding class that incidentally has declared a method named `maxByteAlignment`.

      Via reflection, a new method can be discovered.
      Show
      The interface `MemorySegment` is sealed and only permits internal implementations. Consequently, there could be no overriding class that incidentally has declared a method named `maxByteAlignment`. Via reflection, a new method can be discovered.
    • Java API
    • SE

      Summary

      Add a new method MemorySegment.maxByteAlignment() to allow clients to easily check if a MemorySegment is aligned with any given MemoryLayout alignment constraint, regardless if the segment is a heap or a native segment.

      Problem

      The current FFM API lacks the ability to check if a segment is properly aligned to a layout. This is especially difficult to do if the segment is a heap segment.

      Solution

      Add a method that returns the maximum alignment for a segment. This would allow uncomplicated testing if a given segment can meet the alignment requirements of a certain layout:

      boolean isAligned = segment.maxByteAlignment() >= layout.byteAlignment();

      Computing the maximum byte alignment for native segments can be done using Long.lowestOneBit(address()). Special care must be taken when handling native segments whose address is zero (e.g. the NULL segment), as in these cases outlined strategy would return a maximum alignment of zero, which would not be very useful, given an alignment check like the one written above. For this reason, if a native segment has address zero, we cap the maximum alignment to the highest positive power of two (i.e. 1L << 62). That is, such segments are compatible with the highest possible alignment constraint that can be expressed by the memory layout API.

      The maximum byte alignment for heap segments is also computed using the address but is further capped by the backing array type's alignment (e.g. an int array is 4-byte aligned).

      Specification

      diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
      index a58595cb5416b..bf35d710120d2 100644
      --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
      +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
      
      @@ -95,6 +94,11 @@
        * address of the region of memory which backs the segment.</li>
        * </ul>
        * <p>
      + * Every memory segment has a {@linkplain #maxByteAlignment() maximum byte alignment},
      + * expressed as a {@code long} value. The maximum alignment is always a power of two,
      + * derived from the segment address, and the segment type, as explained in more detail
      + * <a href="#segment-alignment">below</a>.
      + * <p>
        * Every memory segment has a {@linkplain #byteSize() size}. The size of a heap segment
        * is derived from the Java array from which it is obtained. This size is predictable
        * across Java runtimes. The size of a native segment is either passed explicitly
      @@ -394,6 +398,14 @@
        * byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, 0); // ok: ValueLayout.JAVA_INT_UNALIGNED.byteAlignment() == ValueLayout.JAVA_BYTE.byteAlignment()
        * }
        *
      + * Clients can use the {@linkplain MemorySegment#maxByteAlignment()} method to check if
      + * a memory segment supports the alignment constraint of a memory layout, as follows:
      + * {@snippet lang=java:
      + * MemoryLayout layout = ...
      + * MemorySegment segment = ...
      + * boolean isAligned = segment.maxByteAlignment() >= layout.byteAlignment();
      + * }
      + *
        * <h2 id="wrapping-addresses">Zero-length memory segments</h2>
        *
        * When interacting with <a href="package-summary.html#ffa">foreign functions</a>, it is
      @@ -589,6 +601,26 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
            */
           long byteSize();
      
      +    /**
      +     * {@return the <a href="#segment-alignment">maximum byte alignment</a>
      +     * associated with this memory segment}
      +     * <p>
      +     * The returned alignment is always a power of two and is derived from
      +     * the segment {@linkplain #address() address()} and, if it is a heap segment,
      +     * the type of the {@linkplain #heapBase() backing heap storage}.
      +     * <p>
      +     * This method can be used to ensure, a {@code segment} is sufficiently aligned
      +     * with a {@code layout}:
      +     * {@snippet lang=java:
      +     * MemoryLayout layout = ...
      +     * MemorySegment segment = ...
      +     * if (segment.maxByteAlignment() < layout.byteAlignment()) {
      +     *     // Take action (e.g. throw an Exception)
      +     * }
      +     * }
      +     */
      +    long maxByteAlignment();
      +
           /**
            * Returns a slice of this memory segment, at the given offset. The returned
            * segment's address is the address of this segment plus the given offset;
      @@ -1424,6 +1456,9 @@ static MemorySegment ofArray(double[] doubleArray) {
           /**
            * A zero-length native segment modelling the {@code NULL} address. Equivalent to
            * {@code MemorySegment.ofAddress(0L)}.
      +     * <p>
      +     * The {@linkplain MemorySegment#maxByteAlignment() maximum byte alignment} for
      +     * the {@code NULL} segment is of 2<sup>62</sup>.
            */
           MemorySegment NULL = MemorySegment.ofAddress(0L);

            pminborg Per-Ake Minborg
            pminborg Per-Ake Minborg
            Jorn Vernee, Maurizio Cimadamore
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: