1 /*
  2  * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 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;
 72  *     int value;
 73  * } TaggedValues[5];
 74  * }
 75  *
 76  * The above declaration can be modelled using a layout object, as follows:
 77  *
 78  * {@snippet lang=java :
 79  * SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
 80  *     MemoryLayout.structLayout(
 81  *         ValueLayout.JAVA_BYTE.withName("kind"),
 82  *         MemoryLayout.paddingLayout(3),
 83  *         ValueLayout.JAVA_INT.withName("value")
 84  *     )
 85  * ).withName("TaggedValues");
 86  * }
 87  *
 88  * <h2 id="layout-align">Characteristics of memory layouts</h2>
 89  *
 90  * All layouts have a <em>size</em> (expressed in bytes), which is defined as follows:
 91  * <ul>
 92  *     <li>The size of a value layout is determined by the {@linkplain ValueLayout#carrier()}
 93  *     associated with the value layout. That is, the constant {@link ValueLayout#JAVA_INT} has carrier {@code int}, and
 94  *     size of 4 bytes;</li>
 95  *     <li>The size of an address layout is platform-dependent. That is, the constant {@link ValueLayout#ADDRESS}
 96  *     has size of 8 bytes on a 64-bit platform;</li>
 97  *     <li>The size of a padding layout is always provided explicitly, on {@linkplain MemoryLayout#paddingLayout(long) construction};</li>
 98  *     <li>The size of a sequence layout whose element layout is <em>E</em> and element count is <em>L</em>,
 99  *     is the size of <em>E</em>, multiplied by <em>L</em>;</li>
100  *     <li>The size of a struct layout with member layouts <em>M1</em>, <em>M2</em>, ... <em>Mn</em> whose sizes are
101  *     <em>S1</em>, <em>S2</em>, ... <em>Sn</em>, respectively, is <em>S1 + S2 + ... + Sn</em>;</li>
102  *     <li>The size of a union layout <em>U</em> with member layouts <em>M1</em>, <em>M2</em>, ... <em>Mn</em> whose sizes are
103  *     <em>S1</em>, <em>S2</em>, ... <em>Sn</em>, respectively, is <em>max(S1, S2, ... Sn).</em></li>
104  * </ul>
105  * <p>
106  * Furthermore, all layouts have a <em>natural alignment</em> (expressed in bytes) which is defined as follows:
107  * <ul>
108  *     <li>The natural alignment of a padding layout is 1;</li>
109  *     <li>The natural alignment of a value layout whose size is <em>N</em> is <em>N</em>;</li>
110  *     <li>The natural alignment of a sequence layout whose element layout is <em>E</em> is the alignment of <em>E</em>;</li>
111  *     <li>The natural alignment of a group layout with member layouts <em>M1</em>, <em>M2</em>, ... <em>Mn</em> whose
112  *     alignments are <em>A1</em>, <em>A2</em>, ... <em>An</em>, respectively, is <em>max(A1, A2 ... An)</em>.</li>
113  * </ul>
114  * A layout's alignment can be overridden if needed (see {@link MemoryLayout#withByteAlignment(long)}), which can be useful to describe
115  * layouts with weaker or stronger alignment constraints.
116  *
117  * <h2 id="layout-paths">Layout paths</h2>
118  *
119  * A <em>layout path</em> is used to unambiguously select a layout that is nested in some other layout.
120  * Layout paths are typically expressed as a sequence of one or more {@linkplain PathElement path elements}.
121  * (A more formal definition of layout paths is provided <a href="#well-formedness">below</a>).
122  * <p>
123  * Layout paths can be used to:
124  * <ul>
125  *     <li>obtain {@linkplain MemoryLayout#byteOffset(PathElement...) offsets} of arbitrarily nested layouts;</li>
126  *     <li>obtain a {@linkplain #varHandle(PathElement...) var handle} that can be used to access the value corresponding
127  *     to the selected layout;</li>
128  *     <li>{@linkplain #select(PathElement...) select} an arbitrarily nested layout.</li>
129  * </ul>
130  * <p>
131  * For instance, given the {@code taggedValues} sequence layout constructed above, we can obtain the offset,
132  * in bytes, of the member layout named <code>value</code> in the <em>first</em> sequence element, as follows:
133  * {@snippet lang=java :
134  * long valueOffset = taggedValues.byteOffset(PathElement.sequenceElement(0),
135  *                                           PathElement.groupElement("value")); // yields 4
136  * }
137  *
138  * Similarly, we can select the member layout named {@code value}, as follows:
139  * {@snippet lang=java :
140  * MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
141  *                                          PathElement.groupElement("value"));
142  * }
143  *
144  * <h3 id="open-path-elements">Open path elements</h3>
145  *
146  * Some layout path elements, said <em>open path elements</em>, can select multiple layouts at once. For instance,
147  * the open path elements {@link PathElement#sequenceElement()}, {@link PathElement#sequenceElement(long, long)} select
148  * an unspecified element in a sequence layout. A var handle derived from a layout path containing one or more
149  * open path element features additional coordinates of type {@code long}, which can be used by clients to <em>bind</em>
150  * the open elements in the path:
151  *
152  * {@snippet lang=java :
153  * VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
154  *                                                PathElement.groupElement("value"));
155  * MemorySegment valuesSegment = ...
156  * int val = (int) valueHandle.get(valuesSegment, 2); // reads the "value" field of the third struct in the array
157  * }
158  *
159  * <p>
160  * Open path elements also affects the creation of
161  * {@linkplain #byteOffsetHandle(PathElement...) offset-computing method handles}. Each open path element becomes
162  * an additional {@code long} parameter in the obtained method handle. This parameter can be used to specify the index
163  * of the sequence element whose offset is to be computed:
164  *
165  * {@snippet lang=java :
166  * MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
167  *                                                           PathElement.groupElement("kind"));
168  * long offset1 = (long) offsetHandle.invokeExact(1L); // 8
169  * long offset2 = (long) offsetHandle.invokeExact(2L); // 16
170  * }
171  *
172  * <h3 id="deref-path-elements">Dereference path elements</h3>
173  *
174  * A special kind of path element, called <em>dereference path element</em>, allows var handles obtained from
175  * memory layouts to follow pointers. Consider the following layout:
176  *
177  * {@snippet lang=java :
178  * StructLayout RECTANGLE = MemoryLayout.structLayout(
179  *         ValueLayout.ADDRESS.withTargetLayout(
180  *                 MemoryLayout.sequenceLayout(4,
181  *                         MemoryLayout.structLayout(
182  *                                 ValueLayout.JAVA_INT.withName("x"),
183  *                                 ValueLayout.JAVA_INT.withName("y")
184  *                         ).withName("point")
185 *                  )
186 *          ).withName("points")
187  * );
188  * }
189  *
190  * This layout is a struct layout which describe a rectangle. It contains a single field, namely {@code points},
191  * an address layout whose {@linkplain AddressLayout#targetLayout() target layout} is a sequence layout of four
192  * struct layouts. Each struct layout describes a two-dimensional point, and is defined as a pair or
193  * {@link ValueLayout#JAVA_INT} coordinates, with names {@code x} and {@code y}, respectively.
194  * <p>
195  * With dereference path elements, we can obtain a var handle which accesses the {@code y} coordinate of one of the
196  * point in the rectangle, as follows:
197  *
198  * {@snippet lang=java :
199  * VarHandle rectPointYs = RECTANGLE.varHandle(
200  *         PathElement.groupElement("points"),
201  *         PathElement.dereferenceElement(),
202  *         PathElement.sequenceElement(),
203  *         PathElement.groupElement("y")
204  * );
205  *
206  * MemorySegment rect = ...
207  * int rect_y_4 = (int) rectPointYs.get(rect, 2); // rect.points[2]->y
208  * }
209  *
210  * <h3 id="well-formedness">Layout path well-formedness</h3>
211  *
212  * A layout path is applied to a layout {@code C_0}, also called the <em>initial layout</em>. Each path element in a
213  * layout path can be thought of as a function which updates the current layout {@code C_i-1} to some other layout
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);
261 
262     /**
263      * {@return a memory layout with the same characteristics as this layout, but with no name}
264      *
265      * @apiNote This can be useful to compare two layouts that have different names, but are otherwise equal.
266      * @see MemoryLayout#name()
267      */
268     MemoryLayout withoutName();
269 
270     /**
271      * {@return the alignment constraint associated with this layout, expressed in bytes} Layout alignment defines a power
272      * of two {@code A} which is the byte-wise alignment of the layout, where {@code A} is the number of bytes that must be aligned
273      * for any pointer that correctly points to this layout. Thus:
274      *
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.
467      * @throws IllegalArgumentException if the layout path contains one or more <a href=#deref-path-elements>dereference path elements</a>.
468      * @throws IllegalArgumentException if the layout path contains one or more path elements that select one or more
469      * sequence element indices, such as {@link PathElement#sequenceElement(long)} and {@link PathElement#sequenceElement(long, long)}).
470      */
471     default MemoryLayout select(PathElement... elements) {
472         return computePathOp(LayoutPath.rootPath(this), LayoutPath::layout,
473                 EnumSet.of(PathKind.SEQUENCE_ELEMENT_INDEX, PathKind.SEQUENCE_RANGE, PathKind.DEREF_ELEMENT), elements);
474     }
475 
476     private static <Z> Z computePathOp(LayoutPath path, Function<LayoutPath, Z> finalizer,
477                                        Set<PathKind> badKinds, PathElement... elements) {
478         Objects.requireNonNull(elements);
479         for (PathElement e : elements) {
480             LayoutPath.PathElementImpl pathElem = (LayoutPath.PathElementImpl)Objects.requireNonNull(e);
481             if (badKinds.contains(pathElem.kind())) {
482                 throw new IllegalArgumentException(String.format("Invalid %s selection in layout path", pathElem.kind().description()));
483             }
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.
527          *
528          * @param index the index of the member layout element to be selected.
529          * @return a path element which selects the group member layout with the given index.
530          * @throws IllegalArgumentException if {@code index < 0}.
531          */
532         static PathElement groupElement(long index) {
533             if (index < 0) {
534                 throw new IllegalArgumentException("Index < 0");
535             }
536             return new LayoutPath.PathElementImpl(PathKind.GROUP_ELEMENT,
537                     path -> path.groupElement(index));
538         }
539 
540         /**
541          * Returns a path element which selects the element layout at the specified position in a sequence layout.
542          *
543          * @param index the index of the sequence element to be selected.
544          * @return a path element which selects the sequence element layout with the given index.
545          * @throws IllegalArgumentException if {@code index < 0}.
546          */
547         static PathElement sequenceElement(long index) {
548             if (index < 0) {
549                 throw new IllegalArgumentException("Index must be positive: " + index);
550             }
551             return new LayoutPath.PathElementImpl(PathKind.SEQUENCE_ELEMENT_INDEX,
552                                                   path -> path.sequenceElement(index));
553         }
554 
555         /**
556          * Returns an <a href="MemoryLayout.html#open-path-elements">open path element</a> which selects the element
557          * layout in a <em>range</em> of positions in a sequence layout. The range is expressed as a pair of starting
558          * index (inclusive) {@code S} and step factor (which can also be negative) {@code F}.
559          * <p>
560          * The exact sequence element selected by this layout is expressed as an index {@code I}. If {@code C} is the
561          * sequence element count, it follows that {@code 0 <= I < B}, where {@code B} is computed as follows:
562          * <ul>
563          *    <li>if {@code F > 0}, then {@code B = ceilDiv(C - S, F)}</li>
564          *    <li>if {@code F < 0}, then {@code B = ceilDiv(-(S + 1), -F)}</li>
565          * </ul>
566          *
567          * @param start the index of the first sequence element to be selected.
568          * @param step the step factor at which subsequence sequence elements are to be selected.
569          * @return a path element which selects the sequence element layout with the given index.
570          * @throws IllegalArgumentException if {@code start < 0}, or {@code step == 0}.
571          */
572         static PathElement sequenceElement(long start, long step) {
573             if (start < 0) {
574                 throw new IllegalArgumentException("Start index must be positive: " + start);
575             }
576             if (step == 0) {
577                 throw new IllegalArgumentException("Step must be != 0: " + step);
578             }
579             return new LayoutPath.PathElementImpl(PathKind.SEQUENCE_RANGE,
580                                                   path -> path.sequenceElement(start, step));
581         }
582 
583         /**
584          * Returns an <a href="MemoryLayout.html#open-path-elements">open path element</a> which selects an unspecified
585          * element layout in a sequence layout.
586          * <p>
587          * The exact sequence element selected by this layout is expressed as an index {@code I}. If {@code C} is the
588          * sequence element count, it follows that {@code 0 <= I < C}.
589          *
590          * @return a path element which selects an unspecified sequence element layout.
591          */
592         static PathElement sequenceElement() {
593             return new LayoutPath.PathElementImpl(PathKind.SEQUENCE_ELEMENT,
594                                                   LayoutPath::sequenceElement);
595         }
596 
597         /**
598          * Returns a path element which dereferences an address layout as its
599          * {@linkplain AddressLayout#targetLayout() target layout} (where set).
600          *
601          * @return a path element which dereferences an address layout.
602          */
603         static PathElement dereferenceElement() {
604             return new LayoutPath.PathElementImpl(PathKind.DEREF_ELEMENT,
605                     LayoutPath::derefElement);
606         }
607     }
608 
609     /**
610      * Compares the specified object with this layout for equality. Returns {@code true} if and only if the specified
611      * object is also a layout, and it is equal to this layout. Two layouts are considered equal if they are of
612      * the same kind, have the same size, name and alignment constraint. Furthermore, depending on the layout kind, additional
613      * conditions must be satisfied:
614      * <ul>
615      *     <li>two value layouts are considered equal if they have the same {@linkplain ValueLayout#order() order},
616      *     and {@linkplain ValueLayout#carrier() carrier}. Additionally, two address layouts are considered equal if they
617      *     also have the same {@linkplain AddressLayout#targetLayout() target layout};</li>
618      *     <li>two sequence layouts are considered equal if they have the same element count (see {@link SequenceLayout#elementCount()}), and
619      *     if their element layouts (see {@link SequenceLayout#elementLayout()}) are also equal;</li>
620      *     <li>two group layouts are considered equal if they are of the same type (see {@link StructLayout},
621      *     {@link UnionLayout}) and if their member layouts (see {@link GroupLayout#memberLayouts()}) are also equal.</li>
622      * </ul>
623      *
624      * @param other the object to be compared for equality with this layout.
625      * @return {@code true} if the specified object is equal to this layout.
626      */
627     boolean equals(Object other);
628 
629     /**
630      * {@return the hash code value for this layout}
631      */
632     int hashCode();
633 
634     /**
635      * {@return the string representation of this layout}
636      */
637     @Override
638     String toString();
639 
640     /**
641      * Creates a padding layout with the given byte size. The alignment constraint of the returned layout
642      * is 1. As such, regardless of its size, in the absence of an {@linkplain #withByteAlignment(long) explicit}
643      * alignment constraint, a padding layout does not affect the natural alignment of the group or sequence layout
644      * it is nested into.
645      *
646      * @param byteSize the padding size (expressed in bytes).
647      * @return the new selector layout.
648      * @throws IllegalArgumentException if {@code byteSize <= 0}.
649      */
650     static PaddingLayout paddingLayout(long byteSize) {
651         return PaddingLayoutImpl.of(MemoryLayoutUtil.requireByteSizeValid(byteSize, false));
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:
710      * structLayout(JAVA_SHORT, MemoryLayout.paddingLayout(2), JAVA_INT);
711      * }
712      *
713      * Or, alternatively, they can use a member layout which features a smaller alignment constraint. This will result
714      * in a <em>packed</em> struct layout:
715      *
716      * {@snippet lang = java:
717      * structLayout(JAVA_SHORT, JAVA_INT.withByteAlignment(2));
718      * }
719      */
720     static StructLayout structLayout(MemoryLayout... elements) {
721         Objects.requireNonNull(elements);
722         return Utils.wrapOverflow(() ->
723                 StructLayoutImpl.of(Stream.of(elements)
724                         .map(Objects::requireNonNull)
725                         .toList()));
726     }
727 
728     /**
729      * Creates a union layout with the given member layouts.
730      *
731      * @param elements The member layouts of the union layout.
732      * @return a union layout with the given member layouts.
733      */
734     static UnionLayout unionLayout(MemoryLayout... elements) {
735         Objects.requireNonNull(elements);
736         return UnionLayoutImpl.of(Stream.of(elements)
737                 .map(Objects::requireNonNull)
738                 .toList());
739     }
740 }