< prev index next >

src/java.base/share/classes/java/lang/foreign/MemoryLayout.java

Print this page

 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.foreign;
 27 
 28 import java.lang.invoke.MethodHandle;
 29 import java.lang.invoke.MethodHandles;

 30 import java.lang.invoke.VarHandle;
 31 import java.util.EnumSet;
 32 import java.util.Objects;
 33 import java.util.Optional;
 34 import java.util.Set;
 35 import java.util.function.Function;
 36 import java.util.stream.Stream;
 37 
 38 import jdk.internal.foreign.LayoutPath;
 39 import jdk.internal.foreign.LayoutPath.PathElementImpl.PathKind;
 40 import jdk.internal.foreign.Utils;
 41 import jdk.internal.foreign.layout.MemoryLayoutUtil;
 42 import jdk.internal.foreign.layout.PaddingLayoutImpl;
 43 import jdk.internal.foreign.layout.SequenceLayoutImpl;
 44 import jdk.internal.foreign.layout.StructLayoutImpl;
 45 import jdk.internal.foreign.layout.UnionLayoutImpl;
 46 import jdk.internal.javac.PreviewFeature;
 47 
 48 /**
 49  * A memory layout describes the contents of a memory segment.
 50  * <p>
 51  * There are two leaves in the layout hierarchy, {@linkplain ValueLayout value layouts}, which are used to represent values of given size and kind (see
 52  * and {@linkplain PaddingLayout padding layouts} which are used, as the name suggests, to represent a portion of a memory
 53  * segment whose contents should be ignored, and which are primarily present for alignment reasons.
 54  * Some common value layout constants, such as {@link ValueLayout#JAVA_INT} and {@link ValueLayout#JAVA_FLOAT_UNALIGNED}
 55  * are defined in the {@link ValueLayout} class. A special kind of value layout, namely an {@linkplain AddressLayout address layout},
 56  * is used to model values that denote the address of a region of memory.
 57  * <p>
 58  * More complex layouts can be derived from simpler ones: a {@linkplain SequenceLayout sequence layout} denotes a
 59  * homogeneous repetition of zero or more occurrences of an element layout; a {@linkplain GroupLayout group layout}
 60  * denotes a heterogeneous aggregation of zero or more member layouts. Group layouts come in two
 61  * flavors: {@linkplain StructLayout struct layouts}, where member layouts are laid out one after the other, and
 62  * {@linkplain UnionLayout union layouts} where member layouts are laid out at the same starting offset.
 63  * <p>
 64  * Layouts can be optionally associated with a <em>name</em>. A layout name can be referred to when
 65  * constructing <a href="MemoryLayout.html#layout-paths"><em>layout paths</em></a>.
 66  * <p>
 67  * Consider the following struct declaration in C:
 68  *
 69  * {@snippet lang=c :
 70  * typedef struct {
 71  *     char kind;

214  * {@code C_i}. That is, for each path element {@code E1, E2, ... En}, in a layout path {@code P}, we compute
215  * {@code C_i = f_i(C_i-1)}, where {@code f_i} is the selection function associated with the path element under consideration,
216  * denoted as {@code E_i}. The final layout {@code C_i} is also called the <em>selected layout</em>.
217  * <p>
218  * A layout path {@code P} is considered well-formed for an initial layout {@code C_0} if all its path elements
219  * {@code E1, E2, ... En} are well-formed for their corresponding input layouts {@code C_0, C_1, ... C_n-1}.
220  * A path element {@code E} is considered well-formed for a layout {@code L} if any of the following is true:
221  * <ul>
222  * <li>{@code L} is a sequence layout and {@code E} is a sequence path element (one of {@link PathElement#sequenceElement(long)},
223  * {@link PathElement#sequenceElement(long, long)} or {@link PathElement#sequenceElement()}). Moreover, if {@code E}
224  * contains one or more sequence indices, such indices have to be compatible with the sequence layout's element count;</li>
225  * <li>{@code L} is a group layout and {@code E} is a group path element (one of {@link PathElement#groupElement(String)}
226  * or {@link PathElement#groupElement(long)}). Moreover, the group path element must refer to a valid member layout in
227  * {@code L}, either by name, or index;</li>
228  * <li>{@code L} is an address layout and {@code E} is a {@linkplain PathElement#dereferenceElement() dereference path element}.
229  * Moreover, {@code L} must define some {@linkplain AddressLayout#targetLayout() target layout}.</li>
230  * </ul>
231  * Any attempt to provide a layout path {@code P} that is not well-formed for an initial layout {@code C_0} will result
232  * in an {@link IllegalArgumentException}.
233  *





































234  * @implSpec
235  * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
236  *
237  * @sealedGraph
238  * @since 19
239  */
240 @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
241 public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, PaddingLayout, ValueLayout {
242 
243     /**
244      * {@return the layout size, in bytes}
245      */
246     long byteSize();
247 
248     /**
249      * {@return the name (if any) associated with this layout}
250      * @see MemoryLayout#withName(String)
251      */
252     Optional<String> name();
253 
254     /**
255      * {@return a memory layout with the same characteristics as this layout, but with the given name}
256      *
257      * @param name the layout name.
258      * @see MemoryLayout#name()
259      */
260     MemoryLayout withName(String name);

275      * <ul>
276      * <li>{@code A=1} means unaligned (in the usual sense), which is common in packets.</li>
277      * <li>{@code A=8} means word aligned (on LP64), {@code A=4} int aligned, {@code A=2} short aligned, etc.</li>
278      * <li>{@code A=64} is the most strict alignment required by the x86/SV ABI (for AVX-512 data).</li>
279      * </ul>
280      *
281      * If no explicit alignment constraint was set on this layout (see {@link #withByteAlignment(long)}),
282      * then this method returns the <a href="#layout-align">natural alignment</a> constraint (in bytes) associated with this layout.
283      */
284     long byteAlignment();
285 
286     /**
287      * {@return a memory layout with the same characteristics as this layout, but with the given
288      * alignment constraint (in bytes)}
289      *
290      * @param byteAlignment the layout alignment constraint, expressed in bytes.
291      * @throws IllegalArgumentException if {@code byteAlignment} is not a power of two.
292      */
293     MemoryLayout withByteAlignment(long byteAlignment);
294 






































295     /**
296      * Computes the offset, in bytes, of the layout selected by the given layout path, where the initial layout in the
297      * path is this layout.
298      *
299      * @param elements the layout path elements.
300      * @return The offset, in bytes, of the layout selected by the layout path in {@code elements}.
301      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
302      * @throws IllegalArgumentException if the layout path contains one or more <a href=#open-path-elements>open path elements</a>.
303      * @throws IllegalArgumentException if the layout path contains one or more <a href=#deref-path-elements>dereference path elements</a>.
304      */
305     default long byteOffset(PathElement... elements) {
306         return computePathOp(LayoutPath.rootPath(this), LayoutPath::offset,
307                 EnumSet.of(PathKind.SEQUENCE_ELEMENT, PathKind.SEQUENCE_RANGE, PathKind.DEREF_ELEMENT), elements);
308     }
309 
310     /**
311      * Creates a method handle that computes the offset, in bytes, of the layout selected
312      * by the given layout path, where the initial layout in the path is this layout.
313      * <p>
314      * The returned method handle has the following characteristics:
315      * <ul>
316      *     <li>its return type is {@code long};</li>
317      *     <li>it has as zero or more parameters of type {@code long}, one for each <a href=#open-path-elements>open path element</a>

318      *     in the provided layout path. The order of these parameters corresponds to the order in which the open path
319      *     elements occur in the provided layout path.
320      * </ul>
321      * <p>
322      * The final offset returned by the method handle is computed as follows:
323      *
324      * <blockquote><pre>{@code
325      * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
326      * }</pre></blockquote>
327      *
328      * where {@code x_1}, {@code x_2}, ... {@code x_n} are <em>dynamic</em> values provided as {@code long}
329      * arguments, whereas {@code c_1}, {@code c_2}, ... {@code c_m} are <em>static</em> offset constants
330      * and {@code s_0}, {@code s_1}, ... {@code s_n} are <em>static</em> stride constants which are derived from
331      * the layout path.

332      *
333      * @apiNote The returned method handle can be used to compute a layout offset, similarly to {@link #byteOffset(PathElement...)},
334      * but more flexibly, as some indices can be specified when invoking the method handle.
335      *
336      * @param elements the layout path elements.
337      * @return a method handle that computes the offset, in bytes, of the layout selected by the given layout path.
338      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
339      * @throws IllegalArgumentException if the layout path contains one or more <a href=#deref-path-elements>dereference path elements</a>.
340      */
341     default MethodHandle byteOffsetHandle(PathElement... elements) {
342         return computePathOp(LayoutPath.rootPath(this), LayoutPath::offsetHandle,
343                 EnumSet.of(PathKind.DEREF_ELEMENT), elements);
344     }
345 
346     /**
347      * Creates a var handle that accesses a memory segment at the offset selected by the given layout path,
348      * where the initial layout in the path is this layout.
349      * <p>
350      * The returned var handle has the following characteristics:
351      * <ul>
352      *     <li>its type is derived from the {@linkplain ValueLayout#carrier() carrier} of the
353      *     selected value layout;</li>
354      *     <li>it has as zero or more access coordinates of type {@code long}, one for each
355      *     <a href=#open-path-elements>open path element</a> in the provided layout path. The order of these access
356      *     coordinates corresponds to the order in which the open path elements occur in the provided
357      *     layout path.


358      * </ul>
359      * <p>
360      * The final address accessed by the returned var handle can be computed as follows:
361      *
362      * <blockquote><pre>{@code
363      * address = base(segment) + offset
364      * }</pre></blockquote>
365      *
366      * Where {@code base(segment)} denotes a function that returns the physical base address of the accessed
367      * memory segment. For native segments, this function just returns the native segment's
368      * {@linkplain MemorySegment#address() address}. For heap segments, this function is more complex, as the address
369      * of heap segments is virtualized. The {@code offset} value can be expressed in the following form:
370      *
371      * <blockquote><pre>{@code
372      * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
373      * }</pre></blockquote>
374      *
375      * where {@code x_1}, {@code x_2}, ... {@code x_n} are <em>dynamic</em> values provided as {@code long}
376      * arguments, whereas {@code c_1}, {@code c_2}, ... {@code c_m} are <em>static</em> offset constants
377      * and {@code s_1}, {@code s_2}, ... {@code s_n} are <em>static</em> stride constants which are derived from
378      * the layout path.
379      * <p>
380      * Additionally, the provided dynamic values must conform to bounds which are derived from the layout path, that is,
381      * {@code 0 <= x_i < b_i}, where {@code 1 <= i <= n}, or {@link IndexOutOfBoundsException} is thrown.













382      * <p>
383      * The base address must be <a href="MemorySegment.html#segment-alignment">aligned</a> according to the {@linkplain
384      * #byteAlignment() alignment constraint} of the root layout (this layout). Note that this can be more strict
385      * (but not less) than the alignment constraint of the selected value layout.










386      * <p>
387      * Multiple paths can be chained, with <a href=#deref-path-elements>dereference path elements</a>.
388      * A dereference path element constructs a fresh native memory segment whose base address is the address value
389      * read obtained by accessing a memory segment at the offset determined by the layout path elements immediately preceding
390      * the dereference path element. In other words, if a layout path contains one or more dereference path elements,
391      * the final address accessed by the returned var handle can be computed as follows:
392      *
393      * <blockquote><pre>{@code
394      * address_1 = base(segment) + offset_1
395      * address_2 = base(segment_1) + offset_2
396      * ...
397      * address_k = base(segment_k-1) + offset_k
398      * }</pre></blockquote>


399      *
400      * where {@code k} is the number of dereference path elements in a layout path, {@code segment} is the input segment,
401      * {@code segment_1}, ...  {@code segment_k-1} are the segments obtained by dereferencing the address associated with
402      * a given dereference path element (e.g. {@code segment_1} is a native segment whose base address is {@code address_1}),
403      * and {@code offset_1}, {@code offset_2}, ... {@code offset_k} are the offsets computed by evaluating
404      * the path elements after a given dereference operation (these offsets are obtained using the computation described
405      * above). In these more complex access operations, all memory accesses immediately preceding a dereference operation
406      * (e.g. those at addresses {@code address_1}, {@code address_2}, ...,  {@code address_k-1} are performed using the
407      * {@link VarHandle.AccessMode#GET} access mode.






408      *
409      * @apiNote The resulting var handle features certain <em>access mode restrictions</em>, which are common to all
410      * {@linkplain MethodHandles#memorySegmentViewVarHandle(ValueLayout) memory segment view handles}.
411      *
412      * @param elements the layout path elements.
413      * @return a var handle that accesses a memory segment at the offset selected by the given layout path.
414      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
415      * @throws IllegalArgumentException if the layout selected by the provided path is not a {@linkplain ValueLayout value layout}.
416      * @see MethodHandles#memorySegmentViewVarHandle(ValueLayout)
417      */
418     default VarHandle varHandle(PathElement... elements) {




419         return computePathOp(LayoutPath.rootPath(this), LayoutPath::dereferenceHandle,
420                 Set.of(), elements);
421     }
422 
423     /**
424      * Creates a method handle which, given a memory segment, returns a {@linkplain MemorySegment#asSlice(long,long) slice}
425      * corresponding to the layout selected by the given layout path, where the initial layout in the path is this layout.
426      * <p>
427      * The returned method handle has the following characteristics:
428      * <ul>
429      *     <li>its return type is {@code MemorySegment};</li>
430      *     <li>it has a leading parameter of type {@code MemorySegment}, corresponding to the memory segment
431      *     to be sliced;</li>
432      *     <li>it has as zero or more parameters of type {@code long}, one for each <a href=#open-path-elements>open path element</a>
433      *     in the provided layout path. The order of these parameters corresponds to the order in which the open path
434      *     elements occur in the provided layout path.
435      * </ul>
436      * <p>
437      * The offset of the returned segment is computed as follows:
438      * {@snippet lang=java :
439      * long offset = byteOffset(elements);
440      * long size = select(elements).byteSize();
441      * MemorySegment slice = segment.asSlice(offset, size);
442      * }
443      * <p>
444      * The segment to be sliced must be <a href="MemorySegment.html#segment-alignment">aligned</a> according to the
445      * {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout). Note that this can be more
446      * strict (but not less) than the alignment constraint of the selected value layout.








447      *
448      * @apiNote The returned method handle can be used to obtain a memory segment slice, similarly to {@link MemorySegment#asSlice(long, long)},
449      * but more flexibly, as some indices can be specified when invoking the method handle.
450      *
451      * @param elements the layout path elements.
452      * @return a method handle which is used to slice a memory segment at the offset selected by the given layout path.
453      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
454      * @throws IllegalArgumentException if the layout path contains one or more <a href=#deref-path-elements>dereference path elements</a>.
455      */
456     default MethodHandle sliceHandle(PathElement... elements) {
457         return computePathOp(LayoutPath.rootPath(this), LayoutPath::sliceHandle,
458                 Set.of(PathKind.DEREF_ELEMENT), elements);
459     }
460 
461     /**
462      * Returns the layout selected from the provided path, where the initial layout in the path is this layout.
463      *
464      * @param elements the layout path elements.
465      * @return the layout selected by the layout path in {@code elements}.
466      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.

484             path = pathElem.apply(path);
485         }
486         return finalizer.apply(path);
487     }
488 
489     /**
490      * An element in a <a href="MemoryLayout.html#layout-paths"><em>layout path</em></a>. There
491      * are three kinds of path elements:
492      * <ul>
493      *     <li><em>group path elements</em>, used to select a member layout within a {@link GroupLayout}, either by name or by index;</li>
494      *     <li><em>sequence path elements</em>, used to select one or more sequence element layouts within a {@link SequenceLayout}; and</li>
495      *     <li><em>dereference path elements</em>, used to <a href="MemoryLayout.html#deref-path-elements">dereference</a>
496      *     an address layout as its target layout.</li>
497      * </ul>
498      * Sequence path elements selecting more than one sequence element layout are called
499      * <a href="MemoryLayout.html#open-path-elements">open path elements</a>.
500      *
501      * @implSpec
502      * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
503      *
504      * @since 19
505      */
506     @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
507     sealed interface PathElement permits LayoutPath.PathElementImpl {
508 
509         /**
510          * Returns a path element which selects a member layout with the given name in a group layout.
511          *
512          * @implSpec in case multiple group elements with a matching name exist, the path element returned by this
513          * method will select the first one; that is, the group element with the lowest offset from current path is selected.
514          * In such cases, using {@link #groupElement(long)} might be preferable.
515          *
516          * @param name the name of the member layout to be selected.
517          * @return a path element which selects the group member layout with the given name.
518          */
519         static PathElement groupElement(String name) {
520             Objects.requireNonNull(name);
521             return new LayoutPath.PathElementImpl(PathKind.GROUP_ELEMENT,
522                                                   path -> path.groupElement(name));
523         }
524 
525         /**
526          * Returns a path element which selects a member layout with the given index in a group layout.

652     }
653 
654     /**
655      * Creates a sequence layout with the given element layout and element count.
656      *
657      * @param elementCount the sequence element count.
658      * @param elementLayout the sequence element layout.
659      * @return the new sequence layout with the given element layout and size.
660      * @throws IllegalArgumentException if {@code elementCount} is negative.
661      * @throws IllegalArgumentException if {@code elementLayout.byteSize() * elementCount} overflows.
662      * @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}.
663      */
664     static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayout) {
665         MemoryLayoutUtil.requireNonNegative(elementCount);
666         Objects.requireNonNull(elementLayout);
667         Utils.checkElementAlignment(elementLayout, "Element layout size is not multiple of alignment");
668         return Utils.wrapOverflow(() ->
669                 SequenceLayoutImpl.of(elementCount, elementLayout));
670     }
671 
672     /**
673      * Creates a sequence layout with the given element layout and the maximum element
674      * count such that it does not overflow a {@code long}.
675      *
676      * This is equivalent to the following code:
677      * {@snippet lang = java:
678      * sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout);
679      * }
680      *
681      * @param elementLayout the sequence element layout.
682      * @return a new sequence layout with the given element layout and maximum element count.
683      * @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}.
684      */
685     static SequenceLayout sequenceLayout(MemoryLayout elementLayout) {
686         Objects.requireNonNull(elementLayout);
687         return sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout);
688     }
689 
690     /**
691      * Creates a struct layout with the given member layouts.
692      *
693      * @param elements The member layouts of the struct layout.
694      * @return a struct layout with the given member layouts.
695      * @throws IllegalArgumentException if the sum of the {@linkplain #byteSize() byte sizes} of the member layouts
696      * overflows.
697      * @throws IllegalArgumentException if a member layout in {@code elements} occurs at an offset (relative to the start
698      * of the struct layout) which is not compatible with its alignment constraint.
699      *
700      * @apiNote This factory does not automatically align element layouts, by inserting additional {@linkplain PaddingLayout
701      * padding layout} elements. As such, the following struct layout creation will fail with an exception:
702      *
703      * {@snippet lang = java:
704      * structLayout(JAVA_SHORT, JAVA_INT);
705      * }
706      *
707      * To avoid the exception, clients can either insert additional padding layout elements:
708      *
709      * {@snippet lang = java:

 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.foreign;
 27 
 28 import java.lang.invoke.MethodHandle;
 29 import java.lang.invoke.MethodHandles;
 30 import java.lang.invoke.MethodType;
 31 import java.lang.invoke.VarHandle;
 32 import java.util.EnumSet;
 33 import java.util.Objects;
 34 import java.util.Optional;
 35 import java.util.Set;
 36 import java.util.function.Function;
 37 import java.util.stream.Stream;
 38 
 39 import jdk.internal.foreign.LayoutPath;
 40 import jdk.internal.foreign.LayoutPath.PathElementImpl.PathKind;
 41 import jdk.internal.foreign.Utils;
 42 import jdk.internal.foreign.layout.MemoryLayoutUtil;
 43 import jdk.internal.foreign.layout.PaddingLayoutImpl;
 44 import jdk.internal.foreign.layout.SequenceLayoutImpl;
 45 import jdk.internal.foreign.layout.StructLayoutImpl;
 46 import jdk.internal.foreign.layout.UnionLayoutImpl;
 47 import jdk.internal.vm.annotation.ForceInline;
 48 
 49 /**
 50  * A memory layout describes the contents of a memory segment.
 51  * <p>
 52  * There are two leaves in the layout hierarchy, {@linkplain ValueLayout value layouts}, which are used to represent values of given size and kind
 53  * and {@linkplain PaddingLayout padding layouts} which are used, as the name suggests, to represent a portion of a memory
 54  * segment whose contents should be ignored, and which are primarily present for alignment reasons.
 55  * Some common value layout constants, such as {@link ValueLayout#JAVA_INT} and {@link ValueLayout#JAVA_FLOAT_UNALIGNED}
 56  * are defined in the {@link ValueLayout} class. A special kind of value layout, namely an {@linkplain AddressLayout address layout},
 57  * is used to model values that denote the address of a region of memory.
 58  * <p>
 59  * More complex layouts can be derived from simpler ones: a {@linkplain SequenceLayout sequence layout} denotes a
 60  * homogeneous repetition of zero or more occurrences of an element layout; a {@linkplain GroupLayout group layout}
 61  * denotes a heterogeneous aggregation of zero or more member layouts. Group layouts come in two
 62  * flavors: {@linkplain StructLayout struct layouts}, where member layouts are laid out one after the other, and
 63  * {@linkplain UnionLayout union layouts} where member layouts are laid out at the same starting offset.
 64  * <p>
 65  * Layouts can be optionally associated with a <em>name</em>. A layout name can be referred to when
 66  * constructing <a href="MemoryLayout.html#layout-paths"><em>layout paths</em></a>.
 67  * <p>
 68  * Consider the following struct declaration in C:
 69  *
 70  * {@snippet lang=c :
 71  * typedef struct {
 72  *     char kind;

215  * {@code C_i}. That is, for each path element {@code E1, E2, ... En}, in a layout path {@code P}, we compute
216  * {@code C_i = f_i(C_i-1)}, where {@code f_i} is the selection function associated with the path element under consideration,
217  * denoted as {@code E_i}. The final layout {@code C_i} is also called the <em>selected layout</em>.
218  * <p>
219  * A layout path {@code P} is considered well-formed for an initial layout {@code C_0} if all its path elements
220  * {@code E1, E2, ... En} are well-formed for their corresponding input layouts {@code C_0, C_1, ... C_n-1}.
221  * A path element {@code E} is considered well-formed for a layout {@code L} if any of the following is true:
222  * <ul>
223  * <li>{@code L} is a sequence layout and {@code E} is a sequence path element (one of {@link PathElement#sequenceElement(long)},
224  * {@link PathElement#sequenceElement(long, long)} or {@link PathElement#sequenceElement()}). Moreover, if {@code E}
225  * contains one or more sequence indices, such indices have to be compatible with the sequence layout's element count;</li>
226  * <li>{@code L} is a group layout and {@code E} is a group path element (one of {@link PathElement#groupElement(String)}
227  * or {@link PathElement#groupElement(long)}). Moreover, the group path element must refer to a valid member layout in
228  * {@code L}, either by name, or index;</li>
229  * <li>{@code L} is an address layout and {@code E} is a {@linkplain PathElement#dereferenceElement() dereference path element}.
230  * Moreover, {@code L} must define some {@linkplain AddressLayout#targetLayout() target layout}.</li>
231  * </ul>
232  * Any attempt to provide a layout path {@code P} that is not well-formed for an initial layout {@code C_0} will result
233  * in an {@link IllegalArgumentException}.
234  *
235  * <h2 id="access-mode-restrictions">Access mode restrictions</h2>
236  *
237  * A var handle returned by {@link #varHandle(PathElement...)} or {@link ValueLayout#varHandle()} features certain
238  * access characteristics, which are derived from the selected layout {@code L}:
239  * <ul>
240  * <li>A carrier type {@code T}, derived from {@code L.carrier()}</li>
241  * <li>An alignment constraint {@code A}, derived from {@code L.byteAlignment()}</li>
242  * <li>An access size {@code S}, derived from {@code L.byteSize()}</li>
243  * </ul>
244  * Depending on the above characteristics, the returned var handle might feature certain <i>access mode restrictions</i>.
245  * We say that a var handle is <em>aligned</em> if its alignment constraint {@code A} is compatible with the access size
246  * {@code S}, that is if {@code A >= S}. An aligned var handle is guaranteed to support the following access modes:
247  * <ul>
248  * <li>read write access modes for all {@code T}. On 32-bit platforms, access modes
249  *     {@code get} and {@code set} for {@code long}, {@code double} and {@code MemorySegment}
250  *     are supported but might lead to word tearing, as described in Section {@jls 17.7}.
251  *     of <cite>The Java Language Specification</cite>.
252  * <li>atomic update access modes for {@code int}, {@code long},
253  *     {@code float}, {@code double} and {@link MemorySegment}.
254  *     (Future major platform releases of the JDK may support additional
255  *     types for certain currently unsupported access modes.)
256  * <li>numeric atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}.
257  *     (Future major platform releases of the JDK may support additional
258  *     numeric types for certain currently unsupported access modes.)
259  * <li>bitwise atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}.
260  *     (Future major platform releases of the JDK may support additional
261  *     numeric types for certain currently unsupported access modes.)
262  * </ul>
263  * If {@code T} is {@code float}, {@code double} or {@link MemorySegment} then atomic update access modes compare
264  * values using their bitwise representation (see {@link Float#floatToRawIntBits}, {@link Double#doubleToRawLongBits}
265  * and {@link MemorySegment#address()}, respectively).
266  * <p>
267  * Alternatively, a var handle is <em>unaligned</em> if its alignment constraint {@code A} is incompatible with the
268  * access size {@code S}, that is, if {@code A < S}. An unaligned var handle only supports the {@code get} and {@code set}
269  * access modes. All other access modes will result in {@link UnsupportedOperationException} being thrown. Moreover,
270  * while supported, access modes {@code get} and {@code set} might lead to word tearing.
271  *
272  * @implSpec
273  * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
274  *
275  * @sealedGraph
276  * @since 22
277  */

278 public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, PaddingLayout, ValueLayout {
279 
280     /**
281      * {@return the layout size, in bytes}
282      */
283     long byteSize();
284 
285     /**
286      * {@return the name (if any) associated with this layout}
287      * @see MemoryLayout#withName(String)
288      */
289     Optional<String> name();
290 
291     /**
292      * {@return a memory layout with the same characteristics as this layout, but with the given name}
293      *
294      * @param name the layout name.
295      * @see MemoryLayout#name()
296      */
297     MemoryLayout withName(String name);

312      * <ul>
313      * <li>{@code A=1} means unaligned (in the usual sense), which is common in packets.</li>
314      * <li>{@code A=8} means word aligned (on LP64), {@code A=4} int aligned, {@code A=2} short aligned, etc.</li>
315      * <li>{@code A=64} is the most strict alignment required by the x86/SV ABI (for AVX-512 data).</li>
316      * </ul>
317      *
318      * If no explicit alignment constraint was set on this layout (see {@link #withByteAlignment(long)}),
319      * then this method returns the <a href="#layout-align">natural alignment</a> constraint (in bytes) associated with this layout.
320      */
321     long byteAlignment();
322 
323     /**
324      * {@return a memory layout with the same characteristics as this layout, but with the given
325      * alignment constraint (in bytes)}
326      *
327      * @param byteAlignment the layout alignment constraint, expressed in bytes.
328      * @throws IllegalArgumentException if {@code byteAlignment} is not a power of two.
329      */
330     MemoryLayout withByteAlignment(long byteAlignment);
331 
332     /**
333      * {@return {@code offset + (byteSize() * index)}}
334      *
335      * @param offset the base offset
336      * @param index the index to be scaled by the byte size of this layout
337      * @throws IllegalArgumentException if {@code offset} or {@code index} is negative
338      * @throws ArithmeticException if either the addition or multiplication overflows
339      */
340     @ForceInline
341     default long scale(long offset, long index) {
342         if (offset < 0) {
343             throw new IllegalArgumentException("Negative offset: " + offset);
344         }
345         if (index < 0) {
346             throw new IllegalArgumentException("Negative index: " + index);
347         }
348 
349         return Math.addExact(offset, Math.multiplyExact(byteSize(), index));
350     }
351 
352     /**
353      *{@return a method handle that can be used to invoke {@link #scale(long, long)} on this layout}
354      */
355     default MethodHandle scaleHandle() {
356         class Holder {
357             static final MethodHandle MH_SCALE;
358             static {
359                 try {
360                     MH_SCALE = MethodHandles.lookup().findVirtual(MemoryLayout.class, "scale",
361                             MethodType.methodType(long.class, long.class, long.class));
362                 } catch (ReflectiveOperationException e) {
363                     throw new ExceptionInInitializerError(e);
364                 }
365             }
366         }
367         return Holder.MH_SCALE.bindTo(this);
368     }
369 
370     /**
371      * Computes the offset, in bytes, of the layout selected by the given layout path, where the initial layout in the
372      * path is this layout.
373      *
374      * @param elements the layout path elements.
375      * @return The offset, in bytes, of the layout selected by the layout path in {@code elements}.
376      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
377      * @throws IllegalArgumentException if the layout path contains one or more <a href=#open-path-elements>open path elements</a>.
378      * @throws IllegalArgumentException if the layout path contains one or more <a href=#deref-path-elements>dereference path elements</a>.
379      */
380     default long byteOffset(PathElement... elements) {
381         return computePathOp(LayoutPath.rootPath(this), LayoutPath::offset,
382                 EnumSet.of(PathKind.SEQUENCE_ELEMENT, PathKind.SEQUENCE_RANGE, PathKind.DEREF_ELEMENT), elements);
383     }
384 
385     /**
386      * Creates a method handle that computes the offset, in bytes, of the layout selected
387      * by the given layout path, where the initial layout in the path is this layout.
388      * <p>
389      * The returned method handle has the following characteristics:
390      * <ul>
391      *     <li>its return type is {@code long};</li>
392      *     <li>it has one leading {@code long} parameter representing the base offset;</li>
393      *     <li>it has as zero or more trailing parameters of type {@code long}, one for each <a href=#open-path-elements>open path element</a>
394      *     in the provided layout path. The order of these parameters corresponds to the order in which the open path
395      *     elements occur in the provided layout path.
396      * </ul>
397      * <p>
398      * The final offset returned by the method handle is computed as follows:
399      *
400      * <blockquote><pre>{@code
401      * offset = b + c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
402      * }</pre></blockquote>
403      *
404      * where {@code b} represents the base offset provided as a <em>dynamic</em> {@code long} argument, {@code x_1}, {@code x_2},
405      * ... {@code x_n} represent indices into sequences provided as <em>dynamic</em> {@code long} arguments, whereas
406      * {@code s_1}, {@code s_2}, ... {@code s_n} are <em>static</em> stride constants derived from the size of the element
407      * layout of a sequence, and {@code c_1}, {@code c_2}, ... {@code c_m} are other <em>static</em> offset constants
408      * (such as field offsets) which are derived from the layout path.
409      *
410      * @apiNote The returned method handle can be used to compute a layout offset, similarly to {@link #byteOffset(PathElement...)},
411      * but more flexibly, as some indices can be specified when invoking the method handle.
412      *
413      * @param elements the layout path elements.
414      * @return a method handle that computes the offset, in bytes, of the layout selected by the given layout path.
415      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
416      * @throws IllegalArgumentException if the layout path contains one or more <a href=#deref-path-elements>dereference path elements</a>.
417      */
418     default MethodHandle byteOffsetHandle(PathElement... elements) {
419         return computePathOp(LayoutPath.rootPath(this), LayoutPath::offsetHandle,
420                 EnumSet.of(PathKind.DEREF_ELEMENT), elements);
421     }
422 
423     /**
424      * Creates a var handle that accesses a memory segment at the offset selected by the given layout path,
425      * where the initial layout in the path is this layout.
426      * <p>
427      * The returned var handle has the following characteristics:
428      * <ul>
429      *     <li>its type is derived from the {@linkplain ValueLayout#carrier() carrier} of the
430      *     selected value layout;</li>
431      *     <li>it has a leading parameter of type {@code MemorySegment} representing the accessed segment</li>
432      *     <li>a following {@code long} parameter, corresponding to the base offset, denoted as {@code B};</li>
433      *     <li>it has zero or more trailing access coordinates of type {@code long}, one for each
434      *     <a href=#open-path-elements>open path element</a> in the provided layout path, denoted as
435      *     {@code I1, I2, ... In}, respectively. The order of these access coordinates corresponds to the order
436      *     in which the open path elements occur in the provided layout path.
437      * </ul>
438      * <p>
439      * If the provided layout path {@code P} contains no dereference elements, then the offset of the access operation is
440      * computed as follows:












441      *
442      * {@snippet lang = "java":
443      * offset = this.offsetHandle(P).invokeExact(B, I1, I2, ... In);
444      * }

445      * <p>
446      * Accessing a memory segment using the var handle returned by this method is subject to the following checks:
447      * <ul>
448      *     <li>The physical address of the accessed memory segment must be <a href="MemorySegment.html#segment-alignment">aligned</a>
449      * according to the {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout), or
450      * an {@link IllegalArgumentException} will be issued. Note that the alignment constraint of the root layout
451      * can be more strict (but not less) than the alignment constraint of the selected value layout.</li>
452      *     <li>The offset of the access operation (computed as above) must fall inside the spatial bounds of the
453      * accessed memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case when {@code O + A <= S},
454      * where {@code O} is the accessed offset (computed as above), {@code A} is the size of the selected layout and {@code S}
455      * is the size of the accessed memory segment.</li>
456      *     <li>The accessed memory segment must be {@link MemorySegment#isAccessibleBy(Thread) accessible} from the
457      * thread performing the access operation, or a {@link WrongThreadException} is thrown.</li>
458      *     <li>The {@linkplain MemorySegment#scope() scope} associated with the accessed segment must be
459      * {@linkplain MemorySegment.Scope#isAlive() alive}, or an {@link IllegalStateException} is thrown.</li>
460      * </ul>
461      * <p>
462      * If the selected layout is an {@linkplain AddressLayout address layout}, calling {@link VarHandle#get(Object...)}
463      * on the returned var handle will return a new memory segment. The segment is associated with a scope that is
464      * always alive. Moreover, the size of the segment depends on whether the address layout has a
465      * {@linkplain AddressLayout#targetLayout() target layout}. More specifically:
466      * <ul>
467      *     <li>If the address layout has a target layout {@code T}, then the size of the returned segment
468      *     is {@code T.byteSize()};</li>
469      *     <li>Otherwise, the address layout has no target layout, and the size of the returned segment
470      *     is <a href="MemorySegment.html#wrapping-addresses">zero</a>.</li>
471      * </ul>
472      * Moreover, if the selected layout is an {@linkplain AddressLayout address layout}, calling {@link VarHandle#set(Object...)}
473      * can throw {@link IllegalArgumentException} if the memory segment representing the address to be written is not a
474      * {@linkplain MemorySegment#isNative() native} memory segment.
475      * <p>
476      * If the provided layout path has size {@code m} and contains a dereference path element in position {@code k}
477      * (where {@code k <= m}) then two layout paths {@code P} and {@code P'} are derived, where P contains all the path
478      * elements from 0 to {@code k - 1} and {@code P'} contains all the path elements from {@code k + 1} to
479      * {@code m} (if any). Then, the returned var handle is computed as follows:

480      *
481      * {@snippet lang = "java":
482      * VarHandle baseHandle = this.varHandle(P);
483      * MemoryLayout target = ((AddressLayout)this.select(P)).targetLayout().get();
484      * VarHandle targetHandle = target.varHandle(P');
485      * targetHandle = MethodHandles.insertCoordinates(targetHandle, 1, 0L); // always access nested targets at offset 0
486      * targetHandle = MethodHandles.collectCoordinates(targetHandle, 0,
487      *         baseHandle.toMethodHandle(VarHandle.AccessMode.GET));
488      * }
489      *
490      * (The above can be trivially generalized to cases where the provided layout path contains more than one dereference
491      * path elements).
492      * <p>
493      * As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows:
494      * {@snippet lang = "java":
495      *     GroupLayout grp = java.lang.foreign.MemoryLayout.structLayout(
496      *             MemoryLayout.paddingLayout(4),
497      *             ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
498      *     );
499      * }
500      * To access the member layout named {@code value}, we can construct a var handle as follows:
501      * {@snippet lang = "java":
502      *     VarHandle handle = grp.varHandle(PathElement.groupElement("value")); //(MemorySegment, long) -> int
503      * }
504      *
505      * @apiNote The resulting var handle features certain <a href="#access-mode-restrictions"><em>access mode restrictions</em></a>,
506      * which are common to all var handles derived from memory layouts.
507      *
508      * @param elements the layout path elements.
509      * @return a var handle that accesses a memory segment at the offset selected by the given layout path.
510      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
511      * @throws IllegalArgumentException if the layout selected by the provided path is not a {@linkplain ValueLayout value layout}.

512      */
513     default VarHandle varHandle(PathElement... elements) {
514         Objects.requireNonNull(elements);
515         if (this instanceof ValueLayout vl && elements.length == 0) {
516             return vl.varHandle(); // fast path
517         }
518         return computePathOp(LayoutPath.rootPath(this), LayoutPath::dereferenceHandle,
519                 Set.of(), elements);
520     }
521 
522     /**
523      * Creates a method handle which, given a memory segment, returns a {@linkplain MemorySegment#asSlice(long,long) slice}
524      * corresponding to the layout selected by the given layout path, where the initial layout in the path is this layout.
525      * <p>
526      * The returned method handle has the following characteristics:
527      * <ul>
528      *     <li>its return type is {@code MemorySegment};</li>
529      *     <li>it has a leading parameter of type {@code MemorySegment} corresponding to the memory segment to be sliced</li>
530      *     <li>a following {@code long} parameter, corresponding to the base offset</li>
531      *     <li>it has as zero or more trailing parameters of type {@code long}, one for each <a href=#open-path-elements>open path element</a>
532      *     in the provided layout path. The order of these parameters corresponds to the order in which the open path
533      *     elements occur in the provided layout path.
534      * </ul>
535      * <p>
536      * The offset of the returned segment is computed as if by a call to a
537      * {@linkplain #byteOffsetHandle(PathElement...) byte offset handle} constructed using the given path elements.




538      * <p>
539      * Computing a slice of a memory segment using the method handle returned by this method is subject to the following checks:
540      * <ul>
541      *     <li>The physical address of the accessed memory segment must be <a href="MemorySegment.html#segment-alignment">aligned</a>
542      * according to the {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout), or
543      * an {@link IllegalArgumentException} will be issued. Note that the alignment constraint of the root layout
544      * can be more strict (but not less) than the alignment constraint of the selected layout.</li>
545      *     <li>The start offset of the slicing operation (computed as above) must fall fall inside the spatial bounds of the
546      * accessed memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case when {@code O + A <= S},
547      * where {@code O} is the start offset of the slicing operation (computed as above), {@code A} is the size of the
548      * selected layout and {@code S} is the size of the accessed memory segment.</li>
549      * </ul>
550      *
551      * @apiNote The returned method handle can be used to obtain a memory segment slice, similarly to {@link MemorySegment#asSlice(long, long)},
552      * but more flexibly, as some indices can be specified when invoking the method handle.
553      *
554      * @param elements the layout path elements.
555      * @return a method handle which is used to slice a memory segment at the offset selected by the given layout path.
556      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
557      * @throws IllegalArgumentException if the layout path contains one or more <a href=#deref-path-elements>dereference path elements</a>.
558      */
559     default MethodHandle sliceHandle(PathElement... elements) {
560         return computePathOp(LayoutPath.rootPath(this), LayoutPath::sliceHandle,
561                 Set.of(PathKind.DEREF_ELEMENT), elements);
562     }
563 
564     /**
565      * Returns the layout selected from the provided path, where the initial layout in the path is this layout.
566      *
567      * @param elements the layout path elements.
568      * @return the layout selected by the layout path in {@code elements}.
569      * @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.

587             path = pathElem.apply(path);
588         }
589         return finalizer.apply(path);
590     }
591 
592     /**
593      * An element in a <a href="MemoryLayout.html#layout-paths"><em>layout path</em></a>. There
594      * are three kinds of path elements:
595      * <ul>
596      *     <li><em>group path elements</em>, used to select a member layout within a {@link GroupLayout}, either by name or by index;</li>
597      *     <li><em>sequence path elements</em>, used to select one or more sequence element layouts within a {@link SequenceLayout}; and</li>
598      *     <li><em>dereference path elements</em>, used to <a href="MemoryLayout.html#deref-path-elements">dereference</a>
599      *     an address layout as its target layout.</li>
600      * </ul>
601      * Sequence path elements selecting more than one sequence element layout are called
602      * <a href="MemoryLayout.html#open-path-elements">open path elements</a>.
603      *
604      * @implSpec
605      * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
606      *
607      * @since 22
608      */

609     sealed interface PathElement permits LayoutPath.PathElementImpl {
610 
611         /**
612          * Returns a path element which selects a member layout with the given name in a group layout.
613          *
614          * @implSpec in case multiple group elements with a matching name exist, the path element returned by this
615          * method will select the first one; that is, the group element with the lowest offset from current path is selected.
616          * In such cases, using {@link #groupElement(long)} might be preferable.
617          *
618          * @param name the name of the member layout to be selected.
619          * @return a path element which selects the group member layout with the given name.
620          */
621         static PathElement groupElement(String name) {
622             Objects.requireNonNull(name);
623             return new LayoutPath.PathElementImpl(PathKind.GROUP_ELEMENT,
624                                                   path -> path.groupElement(name));
625         }
626 
627         /**
628          * Returns a path element which selects a member layout with the given index in a group layout.

754     }
755 
756     /**
757      * Creates a sequence layout with the given element layout and element count.
758      *
759      * @param elementCount the sequence element count.
760      * @param elementLayout the sequence element layout.
761      * @return the new sequence layout with the given element layout and size.
762      * @throws IllegalArgumentException if {@code elementCount} is negative.
763      * @throws IllegalArgumentException if {@code elementLayout.byteSize() * elementCount} overflows.
764      * @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}.
765      */
766     static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayout) {
767         MemoryLayoutUtil.requireNonNegative(elementCount);
768         Objects.requireNonNull(elementLayout);
769         Utils.checkElementAlignment(elementLayout, "Element layout size is not multiple of alignment");
770         return Utils.wrapOverflow(() ->
771                 SequenceLayoutImpl.of(elementCount, elementLayout));
772     }
773 


















774     /**
775      * Creates a struct layout with the given member layouts.
776      *
777      * @param elements The member layouts of the struct layout.
778      * @return a struct layout with the given member layouts.
779      * @throws IllegalArgumentException if the sum of the {@linkplain #byteSize() byte sizes} of the member layouts
780      * overflows.
781      * @throws IllegalArgumentException if a member layout in {@code elements} occurs at an offset (relative to the start
782      * of the struct layout) which is not compatible with its alignment constraint.
783      *
784      * @apiNote This factory does not automatically align element layouts, by inserting additional {@linkplain PaddingLayout
785      * padding layout} elements. As such, the following struct layout creation will fail with an exception:
786      *
787      * {@snippet lang = java:
788      * structLayout(JAVA_SHORT, JAVA_INT);
789      * }
790      *
791      * To avoid the exception, clients can either insert additional padding layout elements:
792      *
793      * {@snippet lang = java:
< prev index next >