< prev index next > src/java.base/share/classes/java/lang/foreign/MemoryLayout.java
Print this page
package java.lang.foreign;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
+ import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import jdk.internal.foreign.layout.MemoryLayoutUtil;
import jdk.internal.foreign.layout.PaddingLayoutImpl;
import jdk.internal.foreign.layout.SequenceLayoutImpl;
import jdk.internal.foreign.layout.StructLayoutImpl;
import jdk.internal.foreign.layout.UnionLayoutImpl;
! import jdk.internal.javac.PreviewFeature;
/**
* A memory layout describes the contents of a memory segment.
* <p>
! * There are two leaves in the layout hierarchy, {@linkplain ValueLayout value layouts}, which are used to represent values of given size and kind (see
* and {@linkplain PaddingLayout padding layouts} which are used, as the name suggests, to represent a portion of a memory
* segment whose contents should be ignored, and which are primarily present for alignment reasons.
* Some common value layout constants, such as {@link ValueLayout#JAVA_INT} and {@link ValueLayout#JAVA_FLOAT_UNALIGNED}
* are defined in the {@link ValueLayout} class. A special kind of value layout, namely an {@linkplain AddressLayout address layout},
* is used to model values that denote the address of a region of memory.
import jdk.internal.foreign.layout.MemoryLayoutUtil;
import jdk.internal.foreign.layout.PaddingLayoutImpl;
import jdk.internal.foreign.layout.SequenceLayoutImpl;
import jdk.internal.foreign.layout.StructLayoutImpl;
import jdk.internal.foreign.layout.UnionLayoutImpl;
! import jdk.internal.vm.annotation.ForceInline;
/**
* A memory layout describes the contents of a memory segment.
* <p>
! * There are two leaves in the layout hierarchy, {@linkplain ValueLayout value layouts}, which are used to represent values of given size and kind
* and {@linkplain PaddingLayout padding layouts} which are used, as the name suggests, to represent a portion of a memory
* segment whose contents should be ignored, and which are primarily present for alignment reasons.
* Some common value layout constants, such as {@link ValueLayout#JAVA_INT} and {@link ValueLayout#JAVA_FLOAT_UNALIGNED}
* are defined in the {@link ValueLayout} class. A special kind of value layout, namely an {@linkplain AddressLayout address layout},
* is used to model values that denote the address of a region of memory.
* Moreover, {@code L} must define some {@linkplain AddressLayout#targetLayout() target layout}.</li>
* </ul>
* Any attempt to provide a layout path {@code P} that is not well-formed for an initial layout {@code C_0} will result
* in an {@link IllegalArgumentException}.
*
* @implSpec
* Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
*
* @sealedGraph
! * @since 19
*/
- @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, PaddingLayout, ValueLayout {
/**
* {@return the layout size, in bytes}
*/
* Moreover, {@code L} must define some {@linkplain AddressLayout#targetLayout() target layout}.</li>
* </ul>
* Any attempt to provide a layout path {@code P} that is not well-formed for an initial layout {@code C_0} will result
* in an {@link IllegalArgumentException}.
*
+ * <h2 id="access-mode-restrictions">Access mode restrictions</h2>
+ *
+ * A var handle returned by {@link #varHandle(PathElement...)} or {@link ValueLayout#varHandle()} features certain
+ * access characteristics, which are derived from the selected layout {@code L}:
+ * <ul>
+ * <li>A carrier type {@code T}, derived from {@code L.carrier()}</li>
+ * <li>An alignment constraint {@code A}, derived from {@code L.byteAlignment()}</li>
+ * <li>An access size {@code S}, derived from {@code L.byteSize()}</li>
+ * </ul>
+ * Depending on the above characteristics, the returned var handle might feature certain <i>access mode restrictions</i>.
+ * We say that a var handle is <em>aligned</em> if its alignment constraint {@code A} is compatible with the access size
+ * {@code S}, that is if {@code A >= S}. An aligned var handle is guaranteed to support the following access modes:
+ * <ul>
+ * <li>read write access modes for all {@code T}. On 32-bit platforms, access modes
+ * {@code get} and {@code set} for {@code long}, {@code double} and {@code MemorySegment}
+ * are supported but might lead to word tearing, as described in Section {@jls 17.7}.
+ * of <cite>The Java Language Specification</cite>.
+ * <li>atomic update access modes for {@code int}, {@code long},
+ * {@code float}, {@code double} and {@link MemorySegment}.
+ * (Future major platform releases of the JDK may support additional
+ * types for certain currently unsupported access modes.)
+ * <li>numeric atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}.
+ * (Future major platform releases of the JDK may support additional
+ * numeric types for certain currently unsupported access modes.)
+ * <li>bitwise atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}.
+ * (Future major platform releases of the JDK may support additional
+ * numeric types for certain currently unsupported access modes.)
+ * </ul>
+ * If {@code T} is {@code float}, {@code double} or {@link MemorySegment} then atomic update access modes compare
+ * values using their bitwise representation (see {@link Float#floatToRawIntBits}, {@link Double#doubleToRawLongBits}
+ * and {@link MemorySegment#address()}, respectively).
+ * <p>
+ * Alternatively, a var handle is <em>unaligned</em> if its alignment constraint {@code A} is incompatible with the
+ * access size {@code S}, that is, if {@code A < S}. An unaligned var handle only supports the {@code get} and {@code set}
+ * access modes. All other access modes will result in {@link UnsupportedOperationException} being thrown. Moreover,
+ * while supported, access modes {@code get} and {@code set} might lead to word tearing.
+ *
* @implSpec
* Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
*
* @sealedGraph
! * @since 22
*/
public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, PaddingLayout, ValueLayout {
/**
* {@return the layout size, in bytes}
*/
* @param byteAlignment the layout alignment constraint, expressed in bytes.
* @throws IllegalArgumentException if {@code byteAlignment} is not a power of two.
*/
MemoryLayout withByteAlignment(long byteAlignment);
+ /**
+ * {@return {@code offset + (byteSize() * index)}}
+ *
+ * @param offset the base offset
+ * @param index the index to be scaled by the byte size of this layout
+ * @throws IllegalArgumentException if {@code offset} or {@code index} is negative
+ * @throws ArithmeticException if either the addition or multiplication overflows
+ */
+ @ForceInline
+ default long scale(long offset, long index) {
+ if (offset < 0) {
+ throw new IllegalArgumentException("Negative offset: " + offset);
+ }
+ if (index < 0) {
+ throw new IllegalArgumentException("Negative index: " + index);
+ }
+
+ return Math.addExact(offset, Math.multiplyExact(byteSize(), index));
+ }
+
+ /**
+ *{@return a method handle that can be used to invoke {@link #scale(long, long)} on this layout}
+ */
+ default MethodHandle scaleHandle() {
+ class Holder {
+ static final MethodHandle MH_SCALE;
+ static {
+ try {
+ MH_SCALE = MethodHandles.lookup().findVirtual(MemoryLayout.class, "scale",
+ MethodType.methodType(long.class, long.class, long.class));
+ } catch (ReflectiveOperationException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+ }
+ return Holder.MH_SCALE.bindTo(this);
+ }
+
/**
* Computes the offset, in bytes, of the layout selected by the given layout path, where the initial layout in the
* path is this layout.
*
* @param elements the layout path elements.
* by the given layout path, where the initial layout in the path is this layout.
* <p>
* The returned method handle has the following characteristics:
* <ul>
* <li>its return type is {@code long};</li>
! * <li>it has as zero or more parameters of type {@code long}, one for each <a href=#open-path-elements>open path element</a>
* in the provided layout path. The order of these parameters corresponds to the order in which the open path
* elements occur in the provided layout path.
* </ul>
* <p>
* The final offset returned by the method handle is computed as follows:
*
* <blockquote><pre>{@code
! * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
* }</pre></blockquote>
*
! * where {@code x_1}, {@code x_2}, ... {@code x_n} are <em>dynamic</em> values provided as {@code long}
! * arguments, whereas {@code c_1}, {@code c_2}, ... {@code c_m} are <em>static</em> offset constants
! * and {@code s_0}, {@code s_1}, ... {@code s_n} are <em>static</em> stride constants which are derived from
! * the layout path.
*
* @apiNote The returned method handle can be used to compute a layout offset, similarly to {@link #byteOffset(PathElement...)},
* but more flexibly, as some indices can be specified when invoking the method handle.
*
* @param elements the layout path elements.
* by the given layout path, where the initial layout in the path is this layout.
* <p>
* The returned method handle has the following characteristics:
* <ul>
* <li>its return type is {@code long};</li>
! * <li>it has one leading {@code long} parameter representing the base offset;</li>
+ * <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>
* in the provided layout path. The order of these parameters corresponds to the order in which the open path
* elements occur in the provided layout path.
* </ul>
* <p>
* The final offset returned by the method handle is computed as follows:
*
* <blockquote><pre>{@code
! * offset = b + c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
* }</pre></blockquote>
*
! * where {@code b} represents the base offset provided as a <em>dynamic</em> {@code long} argument, {@code x_1}, {@code x_2},
! * ... {@code x_n} represent indices into sequences provided as <em>dynamic</em> {@code long} arguments, whereas
! * {@code s_1}, {@code s_2}, ... {@code s_n} are <em>static</em> stride constants derived from the size of the element
! * layout of a sequence, and {@code c_1}, {@code c_2}, ... {@code c_m} are other <em>static</em> offset constants
+ * (such as field offsets) which are derived from the layout path.
*
* @apiNote The returned method handle can be used to compute a layout offset, similarly to {@link #byteOffset(PathElement...)},
* but more flexibly, as some indices can be specified when invoking the method handle.
*
* @param elements the layout path elements.
* <p>
* The returned var handle has the following characteristics:
* <ul>
* <li>its type is derived from the {@linkplain ValueLayout#carrier() carrier} of the
* selected value layout;</li>
! * <li>it has as zero or more access coordinates of type {@code long}, one for each
! * <a href=#open-path-elements>open path element</a> in the provided layout path. The order of these access
! * coordinates corresponds to the order in which the open path elements occur in the provided
! * layout path.
* </ul>
* <p>
! * The final address accessed by the returned var handle can be computed as follows:
! *
- * <blockquote><pre>{@code
- * address = base(segment) + offset
- * }</pre></blockquote>
- *
- * Where {@code base(segment)} denotes a function that returns the physical base address of the accessed
- * memory segment. For native segments, this function just returns the native segment's
- * {@linkplain MemorySegment#address() address}. For heap segments, this function is more complex, as the address
- * of heap segments is virtualized. The {@code offset} value can be expressed in the following form:
- *
- * <blockquote><pre>{@code
- * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
- * }</pre></blockquote>
*
! * where {@code x_1}, {@code x_2}, ... {@code x_n} are <em>dynamic</em> values provided as {@code long}
! * arguments, whereas {@code c_1}, {@code c_2}, ... {@code c_m} are <em>static</em> offset constants
! * and {@code s_1}, {@code s_2}, ... {@code s_n} are <em>static</em> stride constants which are derived from
- * the layout path.
* <p>
! * Additionally, the provided dynamic values must conform to bounds which are derived from the layout path, that is,
! * {@code 0 <= x_i < b_i}, where {@code 1 <= i <= n}, or {@link IndexOutOfBoundsException} is thrown.
* <p>
! * The base address must be <a href="MemorySegment.html#segment-alignment">aligned</a> according to the {@linkplain
! * #byteAlignment() alignment constraint} of the root layout (this layout). Note that this can be more strict
! * (but not less) than the alignment constraint of the selected value layout.
* <p>
! * Multiple paths can be chained, with <a href=#deref-path-elements>dereference path elements</a>.
! * A dereference path element constructs a fresh native memory segment whose base address is the address value
! * read obtained by accessing a memory segment at the offset determined by the layout path elements immediately preceding
! * the dereference path element. In other words, if a layout path contains one or more dereference path elements,
- * the final address accessed by the returned var handle can be computed as follows:
*
! * <blockquote><pre>{@code
! * address_1 = base(segment) + offset_1
! * address_2 = base(segment_1) + offset_2
! * ...
! * address_k = base(segment_k-1) + offset_k
! * }</pre></blockquote>
*
! * where {@code k} is the number of dereference path elements in a layout path, {@code segment} is the input segment,
! * {@code segment_1}, ... {@code segment_k-1} are the segments obtained by dereferencing the address associated with
! * a given dereference path element (e.g. {@code segment_1} is a native segment whose base address is {@code address_1}),
! * and {@code offset_1}, {@code offset_2}, ... {@code offset_k} are the offsets computed by evaluating
! * the path elements after a given dereference operation (these offsets are obtained using the computation described
! * above). In these more complex access operations, all memory accesses immediately preceding a dereference operation
! * (e.g. those at addresses {@code address_1}, {@code address_2}, ..., {@code address_k-1} are performed using the
! * {@link VarHandle.AccessMode#GET} access mode.
*
! * @apiNote The resulting var handle features certain <em>access mode restrictions</em>, which are common to all
! * {@linkplain MethodHandles#memorySegmentViewVarHandle(ValueLayout) memory segment view handles}.
*
* @param elements the layout path elements.
* @return a var handle that accesses a memory segment at the offset selected by the given layout path.
* @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
* @throws IllegalArgumentException if the layout selected by the provided path is not a {@linkplain ValueLayout value layout}.
- * @see MethodHandles#memorySegmentViewVarHandle(ValueLayout)
*/
default VarHandle varHandle(PathElement... elements) {
return computePathOp(LayoutPath.rootPath(this), LayoutPath::dereferenceHandle,
Set.of(), elements);
}
/**
* <p>
* The returned var handle has the following characteristics:
* <ul>
* <li>its type is derived from the {@linkplain ValueLayout#carrier() carrier} of the
* selected value layout;</li>
! * <li>it has a leading parameter of type {@code MemorySegment} representing the accessed segment</li>
! * <li>a following {@code long} parameter, corresponding to the base offset, denoted as {@code B};</li>
! * <li>it has zero or more trailing access coordinates of type {@code long}, one for each
! * <a href=#open-path-elements>open path element</a> in the provided layout path, denoted as
+ * {@code I1, I2, ... In}, respectively. The order of these access coordinates corresponds to the order
+ * in which the open path elements occur in the provided layout path.
* </ul>
* <p>
! * If the provided layout path {@code P} contains no dereference elements, then the offset of the access operation is
! * computed as follows:
*
! * {@snippet lang = "java":
! * offset = this.offsetHandle(P).invokeExact(B, I1, I2, ... In);
! * }
* <p>
! * Accessing a memory segment using the var handle returned by this method is subject to the following checks:
! * <ul>
+ * <li>The physical address of the accessed memory segment must be <a href="MemorySegment.html#segment-alignment">aligned</a>
+ * according to the {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout), or
+ * an {@link IllegalArgumentException} will be issued. Note that the alignment constraint of the root layout
+ * can be more strict (but not less) than the alignment constraint of the selected value layout.</li>
+ * <li>The offset of the access operation (computed as above) must fall inside the spatial bounds of the
+ * accessed memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case when {@code O + A <= S},
+ * where {@code O} is the accessed offset (computed as above), {@code A} is the size of the selected layout and {@code S}
+ * is the size of the accessed memory segment.</li>
+ * <li>The accessed memory segment must be {@link MemorySegment#isAccessibleBy(Thread) accessible} from the
+ * thread performing the access operation, or a {@link WrongThreadException} is thrown.</li>
+ * <li>The {@linkplain MemorySegment#scope() scope} associated with the accessed segment must be
+ * {@linkplain MemorySegment.Scope#isAlive() alive}, or an {@link IllegalStateException} is thrown.</li>
+ * </ul>
* <p>
! * If the selected layout is an {@linkplain AddressLayout address layout}, calling {@link VarHandle#get(Object...)}
! * on the returned var handle will return a new memory segment. The segment is associated with a fresh scope that is
! * always alive. Moreover, the size of the segment depends on whether the address layout has a
+ * {@linkplain AddressLayout#targetLayout() target layout}. More specifically:
+ * <ul>
+ * <li>If the address layout has a target layout {@code T}, then the size of the returned segment
+ * is {@code T.byteSize()};</li>
+ * <li>Otherwise, the address layout has no target layout, and the size of the returned segment
+ * is <a href="MemorySegment.html#wrapping-addresses">zero</a>.</li>
+ * </ul>
+ * Moreover, if the selected layout is an {@linkplain AddressLayout address layout}, calling {@link VarHandle#set(Object...)}
+ * can throw {@link IllegalArgumentException} if the memory segment representing the address to be written is not a
+ * {@linkplain MemorySegment#isNative() native} memory segment.
* <p>
! * If the provided layout path has size {@code m} and contains a dereference path element in position {@code k}
! * (where {@code k <= m}) then two layout paths {@code P} and {@code P'} are derived, where P contains all the path
! * elements from 0 to {@code k - 1} and {@code P'} contains all the path elements from {@code k + 1} to
! * {@code m} (if any). Then, the returned var handle is computed as follows:
*
! * {@snippet lang = "java":
! * VarHandle baseHandle = this.varHandle(P);
! * MemoryLayout target = ((AddressLayout)this.select(P)).targetLayout().get();
! * VarHandle targetHandle = target.varHandle(P');
! * targetHandle = MethodHandles.insertCoordinates(targetHandle, 1, 0L); // always access nested targets at offset 0
! * targetHandle = MethodHandles.collectCoordinates(targetHandle, 0,
+ * baseHandle.toMethodHandle(VarHandle.AccessMode.GET));
+ * }
*
! * (The above can be trivially generalized to cases where the provided layout path contains more than one dereference
! * path elements).
! * <p>
! * As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows:
! * {@snippet lang = "java":
! * GroupLayout grp = java.lang.foreign.MemoryLayout.structLayout(
! * MemoryLayout.paddingLayout(4),
! * ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
+ * );
+ * }
+ * To access the member layout named {@code value}, we can construct a var handle as follows:
+ * {@snippet lang = "java":
+ * VarHandle handle = grp.varHandle(PathElement.groupElement("value")); //(MemorySegment, long) -> int
+ * }
*
! * @apiNote The resulting var handle features certain <a href="#access-mode-restrictions"><em>access mode restrictions</em></a>,
! * which are common to all var handles derived from memory layouts.
*
* @param elements the layout path elements.
* @return a var handle that accesses a memory segment at the offset selected by the given layout path.
* @throws IllegalArgumentException if the layout path is not <a href="#well-formedness">well-formed</a> for this layout.
* @throws IllegalArgumentException if the layout selected by the provided path is not a {@linkplain ValueLayout value layout}.
*/
default VarHandle varHandle(PathElement... elements) {
+ Objects.requireNonNull(elements);
+ if (this instanceof ValueLayout vl && elements.length == 0) {
+ return vl.varHandle(); // fast path
+ }
return computePathOp(LayoutPath.rootPath(this), LayoutPath::dereferenceHandle,
Set.of(), elements);
}
/**
* corresponding to the layout selected by the given layout path, where the initial layout in the path is this layout.
* <p>
* The returned method handle has the following characteristics:
* <ul>
* <li>its return type is {@code MemorySegment};</li>
! * <li>it has a leading parameter of type {@code MemorySegment}, corresponding to the memory segment
! * to be sliced;</li>
! * <li>it has as zero or more parameters of type {@code long}, one for each <a href=#open-path-elements>open path element</a>
* in the provided layout path. The order of these parameters corresponds to the order in which the open path
* elements occur in the provided layout path.
* </ul>
* <p>
! * The offset of the returned segment is computed as follows:
! * {@snippet lang=java :
- * long offset = byteOffset(elements);
- * long size = select(elements).byteSize();
- * MemorySegment slice = segment.asSlice(offset, size);
- * }
* <p>
! * The segment to be sliced must be <a href="MemorySegment.html#segment-alignment">aligned</a> according to the
! * {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout). Note that this can be more
! * strict (but not less) than the alignment constraint of the selected value layout.
*
* @apiNote The returned method handle can be used to obtain a memory segment slice, similarly to {@link MemorySegment#asSlice(long, long)},
* but more flexibly, as some indices can be specified when invoking the method handle.
*
* @param elements the layout path elements.
* corresponding to the layout selected by the given layout path, where the initial layout in the path is this layout.
* <p>
* The returned method handle has the following characteristics:
* <ul>
* <li>its return type is {@code MemorySegment};</li>
! * <li>it has a leading parameter of type {@code MemorySegment} corresponding to the memory segment to be sliced</li>
! * <li>a following {@code long} parameter, corresponding to the base offset</li>
! * <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>
* in the provided layout path. The order of these parameters corresponds to the order in which the open path
* elements occur in the provided layout path.
* </ul>
* <p>
! * The offset of the returned segment is computed as if by a call to a
! * {@linkplain #byteOffsetHandle(PathElement...) byte offset handle} constructed using the given path elements.
* <p>
! * Computing a slice of a memory segment using the method handle returned by this method is subject to the following checks:
! * <ul>
! * <li>The physical address of the accessed memory segment must be <a href="MemorySegment.html#segment-alignment">aligned</a>
+ * according to the {@linkplain #byteAlignment() alignment constraint} of the root layout (this layout), or
+ * an {@link IllegalArgumentException} will be issued. Note that the alignment constraint of the root layout
+ * can be more strict (but not less) than the alignment constraint of the selected layout.</li>
+ * <li>The start offset of the slicing operation (computed as above) must fall fall inside the spatial bounds of the
+ * accessed memory segment, or an {@link IndexOutOfBoundsException} is thrown. This is the case when {@code O + A <= S},
+ * where {@code O} is the start offset of the slicing operation (computed as above), {@code A} is the size of the
+ * selected layout and {@code S} is the size of the accessed memory segment.</li>
+ * </ul>
*
* @apiNote The returned method handle can be used to obtain a memory segment slice, similarly to {@link MemorySegment#asSlice(long, long)},
* but more flexibly, as some indices can be specified when invoking the method handle.
*
* @param elements the layout path elements.
* <a href="MemoryLayout.html#open-path-elements">open path elements</a>.
*
* @implSpec
* Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
*
! * @since 19
*/
- @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
sealed interface PathElement permits LayoutPath.PathElementImpl {
/**
* Returns a path element which selects a member layout with the given name in a group layout.
*
* <a href="MemoryLayout.html#open-path-elements">open path elements</a>.
*
* @implSpec
* Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
*
! * @since 22
*/
sealed interface PathElement permits LayoutPath.PathElementImpl {
/**
* Returns a path element which selects a member layout with the given name in a group layout.
*
Utils.checkElementAlignment(elementLayout, "Element layout size is not multiple of alignment");
return Utils.wrapOverflow(() ->
SequenceLayoutImpl.of(elementCount, elementLayout));
}
- /**
- * Creates a sequence layout with the given element layout and the maximum element
- * count such that it does not overflow a {@code long}.
- *
- * This is equivalent to the following code:
- * {@snippet lang = java:
- * sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout);
- * }
- *
- * @param elementLayout the sequence element layout.
- * @return a new sequence layout with the given element layout and maximum element count.
- * @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}.
- */
- static SequenceLayout sequenceLayout(MemoryLayout elementLayout) {
- Objects.requireNonNull(elementLayout);
- return sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout);
- }
-
/**
* Creates a struct layout with the given member layouts.
*
* @param elements The member layouts of the struct layout.
* @return a struct layout with the given member layouts.
< prev index next >