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:
|