mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8308276: Change layout API to work with bytes, not bits
Reviewed-by: psandoz, pminborg
This commit is contained in:
parent
91aeb5de58
commit
5fc9b5787d
93 changed files with 527 additions and 721 deletions
|
@ -38,7 +38,7 @@ import java.util.Optional;
|
|||
/**
|
||||
* A value layout used to model the address of some region of memory. The carrier associated with an address layout is
|
||||
* {@code MemorySegment.class}. The size and alignment of an address layout are platform dependent
|
||||
* (e.g. on a 64-bit platform, the size and alignment of an address layout are set to 64 bits).
|
||||
* (e.g. on a 64-bit platform, the size and alignment of an address layout are set to 8 bytes).
|
||||
* <p>
|
||||
* An address layout may optionally feature a {@linkplain #targetLayout() target layout}. An address layout with
|
||||
* target layout {@code T} can be used to model the address of a region of memory whose layout is {@code T}.
|
||||
|
@ -74,7 +74,7 @@ public sealed interface AddressLayout extends ValueLayout permits ValueLayouts.O
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
AddressLayout withBitAlignment(long bitAlignment);
|
||||
AddressLayout withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
|
|
@ -68,9 +68,9 @@ public sealed interface GroupLayout extends MemoryLayout permits StructLayout, U
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
* @throws IllegalArgumentException if {@code bitAlignment} is less than {@code M}, where {@code M} is the maximum alignment
|
||||
* @throws IllegalArgumentException if {@code byteAlignment} is less than {@code M}, where {@code M} is the maximum alignment
|
||||
* constraint in any of the member layouts associated with this group layout.
|
||||
*/
|
||||
@Override
|
||||
GroupLayout withBitAlignment(long bitAlignment);
|
||||
GroupLayout withByteAlignment(long byteAlignment);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ import jdk.internal.javac.PreviewFeature;
|
|||
* SequenceLayout taggedValues = MemoryLayout.sequenceLayout(5,
|
||||
* MemoryLayout.structLayout(
|
||||
* ValueLayout.JAVA_BYTE.withName("kind"),
|
||||
* MemoryLayout.paddingLayout(24),
|
||||
* MemoryLayout.paddingLayout(3),
|
||||
* ValueLayout.JAVA_INT.withName("value")
|
||||
* )
|
||||
* ).withName("TaggedValues");
|
||||
|
@ -84,7 +84,7 @@ import jdk.internal.javac.PreviewFeature;
|
|||
* <h2 id="layout-align">Size, alignment and byte order</h2>
|
||||
*
|
||||
* All layouts have a size; layout size for value and padding layouts is always explicitly denoted; this means that a layout description
|
||||
* always has the same size in bits, regardless of the platform in which it is used. For derived layouts, the size is computed
|
||||
* always has the same size in bytes, regardless of the platform in which it is used. For derived layouts, the size is computed
|
||||
* as follows:
|
||||
* <ul>
|
||||
* <li>for a sequence layout <em>S</em> whose element layout is <em>E</em> and size is <em>L</em>,
|
||||
|
@ -104,7 +104,7 @@ import jdk.internal.javac.PreviewFeature;
|
|||
* <li>for a group layout <em>G</em> with member layouts <em>M1</em>, <em>M2</em>, ... <em>Mn</em> whose alignments are
|
||||
* <em>A1</em>, <em>A2</em>, ... <em>An</em>, respectively, the natural alignment of <em>G</em> is <em>max(A1, A2 ... An)</em></li>
|
||||
* </ul>
|
||||
* A layout's natural alignment can be overridden if needed (see {@link MemoryLayout#withBitAlignment(long)}), which can be useful to describe
|
||||
* A layout's natural alignment can be overridden if needed (see {@link MemoryLayout#withByteAlignment(long)}), which can be useful to describe
|
||||
* hyper-aligned layouts.
|
||||
* <p>
|
||||
* All value layouts have an <em>explicit</em> byte order (see {@link java.nio.ByteOrder}) which is set when the layout is created.
|
||||
|
@ -115,17 +115,17 @@ import jdk.internal.javac.PreviewFeature;
|
|||
* at a layout nested within the root layout - this is the layout <em>selected</em> by the layout path.
|
||||
* Layout paths are typically expressed as a sequence of one or more {@link PathElement} instances.
|
||||
* <p>
|
||||
* Layout paths are for example useful in order to obtain {@linkplain MemoryLayout#bitOffset(PathElement...) offsets} of
|
||||
* Layout paths are for example useful in order to obtain {@linkplain MemoryLayout#byteOffset(PathElement...) offsets} of
|
||||
* arbitrarily nested layouts inside another layout, to quickly obtain a {@linkplain #varHandle(PathElement...) memory access handle}
|
||||
* corresponding to the selected layout, or to {@linkplain #select(PathElement...) select} an arbitrarily nested layout inside
|
||||
* another layout.
|
||||
* <p>
|
||||
* Such <em>layout paths</em> can be constructed programmatically using the methods in this class.
|
||||
* For instance, given the {@code taggedValues} layout instance constructed as above, we can obtain the offset,
|
||||
* in bits, of the member layout named <code>value</code> in the <em>first</em> sequence element, as follows:
|
||||
* in bytes, of the member layout named <code>value</code> in the <em>first</em> sequence element, as follows:
|
||||
* {@snippet lang=java :
|
||||
* long valueOffset = taggedValues.bitOffset(PathElement.sequenceElement(0),
|
||||
* PathElement.groupElement("value")); // yields 32
|
||||
* long valueOffset = taggedValues.byteOffset(PathElement.sequenceElement(0),
|
||||
* PathElement.groupElement("value")); // yields 4
|
||||
* }
|
||||
*
|
||||
* Similarly, we can select the member layout named {@code value}, as follows:
|
||||
|
@ -151,7 +151,7 @@ import jdk.internal.javac.PreviewFeature;
|
|||
* access coordinate.
|
||||
*
|
||||
* <p>A layout path with free dimensions can also be used to create an offset-computing method handle, using the
|
||||
* {@link #bitOffset(PathElement...)} or {@link #byteOffsetHandle(PathElement...)} method. Again, free dimensions are
|
||||
* {@link #byteOffset(PathElement...)} or {@link #byteOffsetHandle(PathElement...)} method. Again, free dimensions are
|
||||
* translated into {@code long} parameters of the created method handle. The method handle can be used to compute the
|
||||
* offsets of elements of a sequence at different indices, by supplying these indices when invoking the method handle.
|
||||
* For instance:
|
||||
|
@ -172,14 +172,8 @@ import jdk.internal.javac.PreviewFeature;
|
|||
@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
|
||||
public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, PaddingLayout, ValueLayout {
|
||||
|
||||
/**
|
||||
* {@return the layout size, in bits}
|
||||
*/
|
||||
long bitSize();
|
||||
|
||||
/**
|
||||
* {@return the layout size, in bytes}
|
||||
* @throws UnsupportedOperationException if {@code bitSize()} is not a multiple of 8.
|
||||
*/
|
||||
long byteSize();
|
||||
|
||||
|
@ -210,24 +204,6 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
*/
|
||||
MemoryLayout withoutName();
|
||||
|
||||
/**
|
||||
* Returns the alignment constraint associated with this layout, expressed in bits. Layout alignment defines a power
|
||||
* of two {@code A} which is the bit-wise alignment of the layout. If {@code A <= 8} then {@code A/8} is the number of
|
||||
* bytes that must be aligned for any pointer that correctly points to this layout. Thus:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code A=8} means unaligned (in the usual sense), which is common in packets.</li>
|
||||
* <li>{@code A=64} means word aligned (on LP64), {@code A=32} int aligned, {@code A=16} short aligned, etc.</li>
|
||||
* <li>{@code A=512} is the most strict alignment required by the x86/SV ABI (for AVX-512 data).</li>
|
||||
* </ul>
|
||||
*
|
||||
* If no explicit alignment constraint was set on this layout (see {@link #withBitAlignment(long)}),
|
||||
* then this method returns the <a href="#layout-align">natural alignment</a> constraint (in bits) associated with this layout.
|
||||
*
|
||||
* @return the layout alignment constraint, in bits.
|
||||
*/
|
||||
long bitAlignment();
|
||||
|
||||
/**
|
||||
* Returns the alignment constraint associated with this layout, expressed in bytes. Layout alignment defines a power
|
||||
* 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
|
||||
|
@ -239,76 +215,24 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* <li>{@code A=64} is the most strict alignment required by the x86/SV ABI (for AVX-512 data).</li>
|
||||
* </ul>
|
||||
*
|
||||
* If no explicit alignment constraint was set on this layout (see {@link #withBitAlignment(long)}),
|
||||
* If no explicit alignment constraint was set on this layout (see {@link #withByteAlignment(long)}),
|
||||
* then this method returns the <a href="#layout-align">natural alignment</a> constraint (in bytes) associated with this layout.
|
||||
*
|
||||
* @return the layout alignment constraint, in bytes.
|
||||
* @throws UnsupportedOperationException if {@code bitAlignment()} is not a multiple of 8.
|
||||
*/
|
||||
long byteAlignment();
|
||||
|
||||
|
||||
/**
|
||||
* Returns a memory layout of the same type with the same size and name as this layout,
|
||||
* but with the specified alignment constraint (in bits).
|
||||
* but with the specified alignment constraint (in bytes).
|
||||
*
|
||||
* @param bitAlignment the layout alignment constraint, expressed in bits.
|
||||
* @param byteAlignment the layout alignment constraint, expressed in bytes.
|
||||
* @return a memory layout with the given alignment constraint.
|
||||
* @throws IllegalArgumentException if {@code bitAlignment} is not a power of two, or if it's less than 8.
|
||||
* @throws IllegalArgumentException if {@code byteAlignment} is not a power of two, or if it's less than 1.
|
||||
*/
|
||||
MemoryLayout withBitAlignment(long bitAlignment);
|
||||
MemoryLayout withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* Computes the offset, in bits, of the layout selected by the given layout path, where the path is considered rooted in this
|
||||
* layout.
|
||||
*
|
||||
* @param elements the layout path elements.
|
||||
* @return The offset, in bits, of the layout selected by the layout path in {@code elements}.
|
||||
* @throws IllegalArgumentException if the layout path does not select any layout nested in this layout, or if the
|
||||
* layout path contains one or more path elements that select multiple sequence element indices
|
||||
* (see {@link PathElement#sequenceElement()} and {@link PathElement#sequenceElement(long, long)}).
|
||||
* @throws IllegalArgumentException if the layout path contains one or more dereference path elements
|
||||
* (see {@link PathElement#dereferenceElement()}).
|
||||
* @throws NullPointerException if either {@code elements == null}, or if any of the elements
|
||||
* in {@code elements} is {@code null}.
|
||||
*/
|
||||
default long bitOffset(PathElement... elements) {
|
||||
return computePathOp(LayoutPath.rootPath(this), LayoutPath::offset,
|
||||
EnumSet.of(PathKind.SEQUENCE_ELEMENT, PathKind.SEQUENCE_RANGE, PathKind.DEREF_ELEMENT), elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a method handle that can be used to compute the offset, in bits, of the layout selected
|
||||
* by the given layout path, where the path is considered rooted in this layout.
|
||||
*
|
||||
* <p>The returned method handle has a return type of {@code long}, and features as many {@code long}
|
||||
* parameter types as there are free dimensions in the provided layout path (see {@link PathElement#sequenceElement()}),
|
||||
* where the order of the parameters corresponds to the order of the path elements.
|
||||
* The returned method handle can be used to compute a layout offset similar to {@link #bitOffset(PathElement...)},
|
||||
* but where some sequence indices are specified only when invoking the method handle.
|
||||
*
|
||||
* <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.
|
||||
*
|
||||
* @param elements the layout path elements.
|
||||
* @return a method handle that can be used to compute the bit offset of the layout element
|
||||
* specified by the given layout path elements, when supplied with the missing sequence element indices.
|
||||
* @throws IllegalArgumentException if the layout path contains one or more path elements that select
|
||||
* multiple sequence element indices (see {@link PathElement#sequenceElement(long, long)}).
|
||||
* @throws IllegalArgumentException if the layout path contains one or more dereference path elements
|
||||
* (see {@link PathElement#dereferenceElement()}).
|
||||
*/
|
||||
default MethodHandle bitOffsetHandle(PathElement... elements) {
|
||||
return computePathOp(LayoutPath.rootPath(this), LayoutPath::offsetHandle,
|
||||
EnumSet.of(PathKind.SEQUENCE_RANGE, PathKind.DEREF_ELEMENT), elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the offset, in bytes, of the layout selected by the given layout path, where the path is considered rooted in this
|
||||
|
@ -321,12 +245,12 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* (see {@link PathElement#sequenceElement()} and {@link PathElement#sequenceElement(long, long)}).
|
||||
* @throws IllegalArgumentException if the layout path contains one or more dereference path elements
|
||||
* (see {@link PathElement#dereferenceElement()}).
|
||||
* @throws UnsupportedOperationException if {@code bitOffset(elements)} is not a multiple of 8.
|
||||
* @throws NullPointerException if either {@code elements == null}, or if any of the elements
|
||||
* in {@code elements} is {@code null}.
|
||||
*/
|
||||
default long byteOffset(PathElement... elements) {
|
||||
return Utils.bitsToBytes(bitOffset(elements));
|
||||
return computePathOp(LayoutPath.rootPath(this), LayoutPath::offset,
|
||||
EnumSet.of(PathKind.SEQUENCE_ELEMENT, PathKind.SEQUENCE_RANGE, PathKind.DEREF_ELEMENT), elements);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -342,8 +266,7 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* <p>The final offset returned by the method handle is computed as follows:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
* bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
* offset = bitOffset / 8
|
||||
* byteOffset = 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}
|
||||
|
@ -351,9 +274,6 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* and {@code s_0}, {@code s_1}, ... {@code s_n} are <em>static</em> stride constants which are derived from
|
||||
* the layout path.
|
||||
*
|
||||
* <p>The method handle will throw an {@link UnsupportedOperationException} if the computed
|
||||
* offset in bits is not a multiple of 8.
|
||||
*
|
||||
* @param elements the layout path elements.
|
||||
* @return a method handle that can be used to compute the byte offset of the layout element
|
||||
* specified by the given layout path elements, when supplied with the missing sequence element indices.
|
||||
|
@ -363,9 +283,8 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* (see {@link PathElement#dereferenceElement()}).
|
||||
*/
|
||||
default MethodHandle byteOffsetHandle(PathElement... elements) {
|
||||
MethodHandle mh = bitOffsetHandle(elements);
|
||||
mh = MethodHandles.filterReturnValue(mh, Utils.BITS_TO_BYTES);
|
||||
return mh;
|
||||
return computePathOp(LayoutPath.rootPath(this), LayoutPath::offsetHandle,
|
||||
EnumSet.of(PathKind.SEQUENCE_RANGE, PathKind.DEREF_ELEMENT), elements);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -448,8 +367,7 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* <p>The offset of the returned segment is computed as follows:
|
||||
*
|
||||
* <blockquote><pre>{@code
|
||||
* bitOffset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
|
||||
* offset = bitOffset / 8
|
||||
* byteOffset = 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}
|
||||
|
@ -465,12 +383,8 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* where {@code segment} is the segment to be sliced, and where {@code layout} is the layout selected by the given
|
||||
* layout path, as per {@link MemoryLayout#select(PathElement...)}.
|
||||
*
|
||||
* <p>The method handle will throw an {@link UnsupportedOperationException} if the computed
|
||||
* offset in bits is not a multiple of 8.
|
||||
*
|
||||
* @param elements the layout path elements.
|
||||
* @return a method handle which can be used to create a slice of the selected layout element, given a segment.
|
||||
* @throws UnsupportedOperationException if the size of the selected layout in bits is not a multiple of 8.
|
||||
* @throws IllegalArgumentException if the layout path contains one or more dereference path elements
|
||||
* (see {@link PathElement#dereferenceElement()}).
|
||||
*/
|
||||
|
@ -687,14 +601,14 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
String toString();
|
||||
|
||||
/**
|
||||
* Creates a padding layout with the given bitSize and a bit-alignment of eight.
|
||||
* Creates a padding layout with the given byte size and a byte-alignment of one.
|
||||
*
|
||||
* @param bitSize the padding size in bits.
|
||||
* @param byteSize the padding size (expressed in bytes).
|
||||
* @return the new selector layout.
|
||||
* @throws IllegalArgumentException if {@code bitSize <= 0} or {@code bitSize % 8 != 0}
|
||||
* @throws IllegalArgumentException if {@code byteSize <= 0}.
|
||||
*/
|
||||
static PaddingLayout paddingLayout(long bitSize) {
|
||||
return PaddingLayoutImpl.of(MemoryLayoutUtil.requireBitSizeValid(bitSize, false));
|
||||
static PaddingLayout paddingLayout(long byteSize) {
|
||||
return PaddingLayoutImpl.of(MemoryLayoutUtil.requireByteSizeValid(byteSize, false));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -704,7 +618,7 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* @param elementLayout the sequence element layout.
|
||||
* @return the new sequence layout with the given element layout and size.
|
||||
* @throws IllegalArgumentException if {@code elementCount } is negative.
|
||||
* @throws IllegalArgumentException if {@code elementLayout.bitSize() % elementLayout.bitAlignment() != 0}.
|
||||
* @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}.
|
||||
*/
|
||||
static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayout) {
|
||||
MemoryLayoutUtil.requireNonNegative(elementCount);
|
||||
|
@ -720,16 +634,16 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
*
|
||||
* This is equivalent to the following code:
|
||||
* {@snippet lang = java:
|
||||
* sequenceLayout(Long.MAX_VALUE / elementLayout.bitSize(), elementLayout);
|
||||
* 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.bitSize() % elementLayout.bitAlignment() != 0}.
|
||||
* @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}.
|
||||
*/
|
||||
static SequenceLayout sequenceLayout(MemoryLayout elementLayout) {
|
||||
Objects.requireNonNull(elementLayout);
|
||||
return sequenceLayout(Long.MAX_VALUE / elementLayout.bitSize(), elementLayout);
|
||||
return sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -737,7 +651,7 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
*
|
||||
* @param elements The member layouts of the struct layout.
|
||||
* @return a struct layout with the given member layouts.
|
||||
* @throws IllegalArgumentException if the sum of the {@linkplain #bitSize() bit sizes} of the member layouts
|
||||
* @throws IllegalArgumentException if the sum of the {@linkplain #byteSize() byte sizes} of the member layouts
|
||||
* overflows.
|
||||
* @throws IllegalArgumentException if a member layout in {@code elements} occurs at an offset (relative to the start
|
||||
* of the struct layout) which is not compatible with its alignment constraint.
|
||||
|
@ -752,14 +666,14 @@ public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, Paddin
|
|||
* To avoid the exception, clients can either insert additional padding layout elements:
|
||||
*
|
||||
* {@snippet lang = java:
|
||||
* structLayout(JAVA_SHORT, MemoryLayout.ofPadding(16), JAVA_INT)
|
||||
* structLayout(JAVA_SHORT, MemoryLayout.ofPadding(2), JAVA_INT)
|
||||
* }
|
||||
*
|
||||
* Or, alternatively, they can use a member layout which features a smaller alignment constraint. This will result
|
||||
* in a <em>packed</em> struct layout:
|
||||
*
|
||||
* {@snippet lang = java:
|
||||
* structLayout(JAVA_SHORT, JAVA_INT.withBitAlignment(16))
|
||||
* structLayout(JAVA_SHORT, JAVA_INT.withByteAlignment(2))
|
||||
* }
|
||||
*/
|
||||
static StructLayout structLayout(MemoryLayout... elements) {
|
||||
|
|
|
@ -379,7 +379,7 @@ import jdk.internal.vm.annotation.ForceInline;
|
|||
* to read a pointer from some memory segment. This can be done via the
|
||||
* {@linkplain MemorySegment#get(AddressLayout, long)} access method. This method accepts an
|
||||
* {@linkplain AddressLayout address layout} (e.g. {@link ValueLayout#ADDRESS}), the layout of the pointer
|
||||
* to be read. For instance on a 64-bit platform, the size of an address layout is 64 bits. The access operation
|
||||
* to be read. For instance on a 64-bit platform, the size of an address layout is 8 bytes. The access operation
|
||||
* also accepts an offset, expressed in bytes, which indicates the position (relative to the start of the memory segment)
|
||||
* at which the pointer is stored. The access operation returns a zero-length native memory segment, backed by a region
|
||||
* of memory whose starting address is the 64-bit value read at the specified offset.
|
||||
|
@ -470,7 +470,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
|||
* @return the element spliterator for this segment
|
||||
* @throws IllegalArgumentException if {@code elementLayout.byteSize() == 0}.
|
||||
* @throws IllegalArgumentException if {@code byteSize() % elementLayout.byteSize() != 0}.
|
||||
* @throws IllegalArgumentException if {@code elementLayout.bitSize() % elementLayout.bitAlignment() != 0}.
|
||||
* @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}.
|
||||
* @throws IllegalArgumentException if this segment is <a href="MemorySegment.html#segment-alignment">incompatible
|
||||
* with the alignment constraint</a> in the provided layout.
|
||||
*/
|
||||
|
@ -487,7 +487,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl {
|
|||
* @return a sequential {@code Stream} over disjoint slices in this segment.
|
||||
* @throws IllegalArgumentException if {@code elementLayout.byteSize() == 0}.
|
||||
* @throws IllegalArgumentException if {@code byteSize() % elementLayout.byteSize() != 0}.
|
||||
* @throws IllegalArgumentException if {@code elementLayout.bitSize() % elementLayout.bitAlignment() != 0}.
|
||||
* @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}.
|
||||
* @throws IllegalArgumentException if this segment is <a href="MemorySegment.html#segment-alignment">incompatible
|
||||
* with the alignment constraint</a> in the provided layout.
|
||||
*/
|
||||
|
|
|
@ -56,6 +56,5 @@ public sealed interface PaddingLayout extends MemoryLayout permits PaddingLayout
|
|||
* {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
PaddingLayout withBitAlignment(long bitAlignment);
|
||||
PaddingLayout withByteAlignment(long byteAlignment);
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ public sealed interface SequenceLayout extends MemoryLayout permits SequenceLayo
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
* @throws IllegalArgumentException if {@code bitAlignment < elementLayout().bitAlignment()}.
|
||||
* @throws IllegalArgumentException if {@code byteAlignment < elementLayout().byteAlignment()}.
|
||||
*/
|
||||
SequenceLayout withBitAlignment(long bitAlignment);
|
||||
SequenceLayout withByteAlignment(long byteAlignment);
|
||||
}
|
||||
|
|
|
@ -56,5 +56,5 @@ public sealed interface StructLayout extends GroupLayout permits StructLayoutImp
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
StructLayout withBitAlignment(long bitAlignment);
|
||||
StructLayout withByteAlignment(long byteAlignment);
|
||||
}
|
||||
|
|
|
@ -56,5 +56,5 @@ public sealed interface UnionLayout extends GroupLayout permits UnionLayoutImpl
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
UnionLayout withBitAlignment(long bitAlignment);
|
||||
UnionLayout withByteAlignment(long byteAlignment);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ import jdk.internal.javac.PreviewFeature;
|
|||
* <em>integral</em> values (either signed or unsigned), <em>floating-point</em> values and
|
||||
* <em>address</em> values.
|
||||
* <p>
|
||||
* Each value layout has a size, an alignment (in bits),
|
||||
* Each value layout has a size, an alignment (both expressed in bytes),
|
||||
* a {@linkplain ByteOrder byte order}, and a <em>carrier</em>, that is, the Java type that should be used when
|
||||
* {@linkplain MemorySegment#get(OfInt, long) accessing} a region of memory using the value layout.
|
||||
* <p>
|
||||
|
@ -129,7 +129,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* featuring {@code shape.length + 1}
|
||||
* {@code long} coordinates.
|
||||
* @throws IllegalArgumentException if {@code shape[i] < 0}, for at least one index {@code i}.
|
||||
* @throws UnsupportedOperationException if {@code bitAlignment() > bitSize()}.
|
||||
* @throws UnsupportedOperationException if {@code byteAlignment() > byteSize()}.
|
||||
* @see MethodHandles#memorySegmentViewVarHandle
|
||||
* @see MemoryLayout#varHandle(PathElement...)
|
||||
* @see SequenceLayout
|
||||
|
@ -152,7 +152,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
ValueLayout withBitAlignment(long bitAlignment);
|
||||
ValueLayout withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* A value layout whose carrier is {@code boolean.class}.
|
||||
|
@ -180,7 +180,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
OfBoolean withBitAlignment(long bitAlignment);
|
||||
OfBoolean withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -216,7 +216,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
OfByte withBitAlignment(long bitAlignment);
|
||||
OfByte withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -253,7 +253,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
OfChar withBitAlignment(long bitAlignment);
|
||||
OfChar withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -290,7 +290,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
OfShort withBitAlignment(long bitAlignment);
|
||||
OfShort withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -327,7 +327,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
OfInt withBitAlignment(long bitAlignment);
|
||||
OfInt withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -363,7 +363,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
OfFloat withBitAlignment(long bitAlignment);
|
||||
OfFloat withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -400,7 +400,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
OfLong withBitAlignment(long bitAlignment);
|
||||
OfLong withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -437,7 +437,7 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
OfDouble withBitAlignment(long bitAlignment);
|
||||
OfDouble withByteAlignment(long byteAlignment);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
@ -449,56 +449,56 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a machine address ({@code size_t}),
|
||||
* bit alignment set to {@code sizeof(size_t) * 8}, byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* byte alignment set to {@code sizeof(size_t)}, byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
AddressLayout ADDRESS = ValueLayouts.OfAddressImpl.of(ByteOrder.nativeOrder());
|
||||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a Java {@code byte},
|
||||
* bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* byte alignment set to 1, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
OfByte JAVA_BYTE = ValueLayouts.OfByteImpl.of(ByteOrder.nativeOrder());
|
||||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a Java {@code boolean},
|
||||
* bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* byte alignment set to 1, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
OfBoolean JAVA_BOOLEAN = ValueLayouts.OfBooleanImpl.of(ByteOrder.nativeOrder());
|
||||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a Java {@code char},
|
||||
* bit alignment set to 16, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* byte alignment set to 2, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
OfChar JAVA_CHAR = ValueLayouts.OfCharImpl.of(ByteOrder.nativeOrder());
|
||||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a Java {@code short},
|
||||
* bit alignment set to 16, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* byte alignment set to 2, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
OfShort JAVA_SHORT = ValueLayouts.OfShortImpl.of(ByteOrder.nativeOrder());
|
||||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a Java {@code int},
|
||||
* bit alignment set to 32, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* byte alignment set to 4, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
OfInt JAVA_INT = ValueLayouts.OfIntImpl.of(ByteOrder.nativeOrder());
|
||||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a Java {@code long},
|
||||
* (platform-dependent) bit alignment set to {@code ADDRESS.bitSize()},
|
||||
* (platform-dependent) byte alignment set to {@code ADDRESS.byteSize()},
|
||||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
OfLong JAVA_LONG = ValueLayouts.OfLongImpl.of(ByteOrder.nativeOrder());
|
||||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a Java {@code float},
|
||||
* bit alignment set to 32, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* byte alignment set to 4, and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
OfFloat JAVA_FLOAT = ValueLayouts.OfFloatImpl.of(ByteOrder.nativeOrder());
|
||||
|
||||
/**
|
||||
* A value layout constant whose size is the same as that of a Java {@code double},
|
||||
* (platform-dependent) bit alignment set to {@code ADDRESS.bitSize()},
|
||||
* (platform-dependent) byte alignment set to {@code ADDRESS.byteSize()},
|
||||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
*/
|
||||
OfDouble JAVA_DOUBLE = ValueLayouts.OfDoubleImpl.of(ByteOrder.nativeOrder());
|
||||
|
@ -508,83 +508,83 @@ public sealed interface ValueLayout extends MemoryLayout permits
|
|||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* {@snippet lang=java :
|
||||
* ADDRESS.withBitAlignment(8);
|
||||
* ADDRESS.withByteAlignment(1);
|
||||
* }
|
||||
* @apiNote Care should be taken when using unaligned value layouts as they may induce
|
||||
* performance and portability issues.
|
||||
*/
|
||||
AddressLayout ADDRESS_UNALIGNED = ADDRESS.withBitAlignment(8);
|
||||
AddressLayout ADDRESS_UNALIGNED = ADDRESS.withByteAlignment(1);
|
||||
|
||||
/**
|
||||
* An unaligned value layout constant whose size is the same as that of a Java {@code char}
|
||||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* {@snippet lang=java :
|
||||
* JAVA_CHAR.withBitAlignment(8);
|
||||
* JAVA_CHAR.withByteAlignment(1);
|
||||
* }
|
||||
* @apiNote Care should be taken when using unaligned value layouts as they may induce
|
||||
* performance and portability issues.
|
||||
*/
|
||||
OfChar JAVA_CHAR_UNALIGNED = JAVA_CHAR.withBitAlignment(8);
|
||||
OfChar JAVA_CHAR_UNALIGNED = JAVA_CHAR.withByteAlignment(1);
|
||||
|
||||
/**
|
||||
* An unaligned value layout constant whose size is the same as that of a Java {@code short}
|
||||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* {@snippet lang=java :
|
||||
* JAVA_SHORT.withBitAlignment(8);
|
||||
* JAVA_SHORT.withByteAlignment(1);
|
||||
* }
|
||||
* @apiNote Care should be taken when using unaligned value layouts as they may induce
|
||||
* performance and portability issues.
|
||||
*/
|
||||
OfShort JAVA_SHORT_UNALIGNED = JAVA_SHORT.withBitAlignment(8);
|
||||
OfShort JAVA_SHORT_UNALIGNED = JAVA_SHORT.withByteAlignment(1);
|
||||
|
||||
/**
|
||||
* An unaligned value layout constant whose size is the same as that of a Java {@code int}
|
||||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* {@snippet lang=java :
|
||||
* JAVA_INT.withBitAlignment(8);
|
||||
* JAVA_INT.withByteAlignment(1);
|
||||
* }
|
||||
* @apiNote Care should be taken when using unaligned value layouts as they may induce
|
||||
* performance and portability issues.
|
||||
*/
|
||||
OfInt JAVA_INT_UNALIGNED = JAVA_INT.withBitAlignment(8);
|
||||
OfInt JAVA_INT_UNALIGNED = JAVA_INT.withByteAlignment(1);
|
||||
|
||||
/**
|
||||
* An unaligned value layout constant whose size is the same as that of a Java {@code long}
|
||||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* {@snippet lang=java :
|
||||
* JAVA_LONG.withBitAlignment(8);
|
||||
* JAVA_LONG.withByteAlignment(1);
|
||||
* }
|
||||
* @apiNote Care should be taken when using unaligned value layouts as they may induce
|
||||
* performance and portability issues.
|
||||
*/
|
||||
OfLong JAVA_LONG_UNALIGNED = JAVA_LONG.withBitAlignment(8);
|
||||
OfLong JAVA_LONG_UNALIGNED = JAVA_LONG.withByteAlignment(1);
|
||||
|
||||
/**
|
||||
* An unaligned value layout constant whose size is the same as that of a Java {@code float}
|
||||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* {@snippet lang=java :
|
||||
* JAVA_FLOAT.withBitAlignment(8);
|
||||
* JAVA_FLOAT.withByteAlignment(1);
|
||||
* }
|
||||
* @apiNote Care should be taken when using unaligned value layouts as they may induce
|
||||
* performance and portability issues.
|
||||
*/
|
||||
OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withBitAlignment(8);
|
||||
OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withByteAlignment(1);
|
||||
|
||||
/**
|
||||
* An unaligned value layout constant whose size is the same as that of a Java {@code double}
|
||||
* and byte order set to {@link ByteOrder#nativeOrder()}.
|
||||
* Equivalent to the following code:
|
||||
* {@snippet lang=java :
|
||||
* JAVA_DOUBLE.withBitAlignment(8);
|
||||
* JAVA_DOUBLE.withByteAlignment(1);
|
||||
* }
|
||||
* @apiNote Care should be taken when using unaligned value layouts as they may induce
|
||||
* performance and portability issues.
|
||||
*/
|
||||
OfDouble JAVA_DOUBLE_UNALIGNED = JAVA_DOUBLE.withBitAlignment(8);
|
||||
OfDouble JAVA_DOUBLE_UNALIGNED = JAVA_DOUBLE.withByteAlignment(1);
|
||||
|
||||
}
|
||||
|
|
|
@ -7964,7 +7964,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||
* <p>As an example, consider the memory layout expressed by a {@link GroupLayout} instance constructed as follows:
|
||||
* {@snippet lang="java" :
|
||||
* GroupLayout seq = java.lang.foreign.MemoryLayout.structLayout(
|
||||
* MemoryLayout.paddingLayout(32),
|
||||
* MemoryLayout.paddingLayout(4),
|
||||
* ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withName("value")
|
||||
* );
|
||||
* }
|
||||
|
|
|
@ -54,10 +54,10 @@ public enum CABI {
|
|||
if (ForeignLinkerSupport.isSupported()) {
|
||||
// figure out the ABI based on the platform
|
||||
String arch = StaticProperty.osArch();
|
||||
long addressSize = ADDRESS.bitSize();
|
||||
long addressSize = ADDRESS.byteSize();
|
||||
// might be running in a 32-bit VM on a 64-bit platform.
|
||||
// addressSize will be correctly 32
|
||||
if ((arch.equals("amd64") || arch.equals("x86_64")) && addressSize == 64) {
|
||||
if ((arch.equals("amd64") || arch.equals("x86_64")) && addressSize == 8) {
|
||||
if (OperatingSystem.isWindows()) {
|
||||
return WIN_64;
|
||||
} else {
|
||||
|
|
|
@ -97,7 +97,7 @@ public class LayoutPath {
|
|||
check(SequenceLayout.class, "attempting to select a sequence element from a non-sequence layout");
|
||||
SequenceLayout seq = (SequenceLayout)layout;
|
||||
MemoryLayout elem = seq.elementLayout();
|
||||
return LayoutPath.nestedPath(elem, offset, addStride(elem.bitSize()), addBound(seq.elementCount()), derefAdapters, this);
|
||||
return LayoutPath.nestedPath(elem, offset, addStride(elem.byteSize()), addBound(seq.elementCount()), derefAdapters, this);
|
||||
}
|
||||
|
||||
public LayoutPath sequenceElement(long start, long step) {
|
||||
|
@ -105,7 +105,7 @@ public class LayoutPath {
|
|||
SequenceLayout seq = (SequenceLayout)layout;
|
||||
checkSequenceBounds(seq, start);
|
||||
MemoryLayout elem = seq.elementLayout();
|
||||
long elemSize = elem.bitSize();
|
||||
long elemSize = elem.byteSize();
|
||||
long nelems = step > 0 ?
|
||||
seq.elementCount() - start :
|
||||
start + 1;
|
||||
|
@ -118,7 +118,7 @@ public class LayoutPath {
|
|||
check(SequenceLayout.class, "attempting to select a sequence element from a non-sequence layout");
|
||||
SequenceLayout seq = (SequenceLayout)layout;
|
||||
checkSequenceBounds(seq, index);
|
||||
long elemSize = seq.elementLayout().bitSize();
|
||||
long elemSize = seq.elementLayout().byteSize();
|
||||
long elemOffset = elemSize * index;
|
||||
return LayoutPath.nestedPath(seq.elementLayout(), offset + elemOffset, strides, bounds, derefAdapters,this);
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ public class LayoutPath {
|
|||
elem = l;
|
||||
break;
|
||||
} else if (g instanceof StructLayout) {
|
||||
offset += l.bitSize();
|
||||
offset += l.byteSize();
|
||||
}
|
||||
}
|
||||
if (elem == null) {
|
||||
|
@ -156,7 +156,7 @@ public class LayoutPath {
|
|||
}
|
||||
elem = g.memberLayouts().get(i);
|
||||
if (g instanceof StructLayout && i < index) {
|
||||
offset += elem.bitSize();
|
||||
offset += elem.byteSize();
|
||||
}
|
||||
}
|
||||
return LayoutPath.nestedPath(elem, this.offset + offset, strides, bounds, derefAdapters, this);
|
||||
|
@ -196,14 +196,14 @@ public class LayoutPath {
|
|||
VarHandle handle = Utils.makeSegmentViewVarHandle(valueLayout);
|
||||
for (int i = strides.length - 1; i >= 0; i--) {
|
||||
MethodHandle collector = MethodHandles.insertArguments(MH_ADD_SCALED_OFFSET, 2,
|
||||
Utils.bitsToBytes(strides[i]),
|
||||
strides[i],
|
||||
bounds[i]);
|
||||
// (J, ...) -> J to (J, J, ...) -> J
|
||||
// i.e. new coord is prefixed. Last coord will correspond to innermost layout
|
||||
handle = MethodHandles.collectCoordinates(handle, 1, collector);
|
||||
}
|
||||
handle = MethodHandles.insertCoordinates(handle, 1,
|
||||
Utils.bitsToBytes(offset));
|
||||
offset);
|
||||
|
||||
if (adapt) {
|
||||
for (int i = derefAdapters.length; i > 0; i--) {
|
||||
|
@ -232,8 +232,7 @@ public class LayoutPath {
|
|||
}
|
||||
|
||||
public MethodHandle sliceHandle() {
|
||||
MethodHandle offsetHandle = offsetHandle(); // bit offset
|
||||
offsetHandle = MethodHandles.filterReturnValue(offsetHandle, Utils.BITS_TO_BYTES); // byte offset
|
||||
MethodHandle offsetHandle = offsetHandle(); // byte offset
|
||||
|
||||
MethodHandle sliceHandle = MH_SLICE; // (MS, long, long) -> MS
|
||||
sliceHandle = MethodHandles.insertArguments(sliceHandle, 2, layout.byteSize()); // (MS, long) -> MS
|
||||
|
|
|
@ -43,8 +43,8 @@ public sealed class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl pe
|
|||
|
||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
// The maximum alignment supported by malloc - typically 16 on
|
||||
// 64-bit platforms and 8 on 32-bit platforms.
|
||||
// The maximum alignment supported by malloc - typically 16 bytes on
|
||||
// 64-bit platforms and 8 bytes on 32-bit platforms.
|
||||
private static final long MAX_MALLOC_ALIGN = Unsafe.ADDRESS_SIZE == 4 ? 8 : 16;
|
||||
private static final boolean SKIP_ZERO_MEMORY = GetBooleanAction.privilegedGetProperty("jdk.internal.foreign.skipZeroMemory");
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ public final class Utils {
|
|||
private static final MethodHandle BOOL_TO_BYTE;
|
||||
private static final MethodHandle ADDRESS_TO_LONG;
|
||||
private static final MethodHandle LONG_TO_ADDRESS;
|
||||
public static final MethodHandle BITS_TO_BYTES;
|
||||
|
||||
static {
|
||||
try {
|
||||
|
@ -76,8 +75,6 @@ public final class Utils {
|
|||
MethodType.methodType(long.class, MemorySegment.class));
|
||||
LONG_TO_ADDRESS = lookup.findStatic(Utils.class, "longToAddress",
|
||||
MethodType.methodType(MemorySegment.class, long.class, long.class, long.class));
|
||||
BITS_TO_BYTES = lookup.findStatic(Utils.class, "bitsToBytes",
|
||||
MethodType.methodType(long.class, long.class));
|
||||
} catch (Throwable ex) {
|
||||
throw new ExceptionInInitializerError(ex);
|
||||
}
|
||||
|
@ -92,11 +89,6 @@ public final class Utils {
|
|||
return ms.asSlice(alignUp(offset, alignment) - offset);
|
||||
}
|
||||
|
||||
public static long bitsToBytes(long bits) {
|
||||
assert Utils.isAligned(bits, 8);
|
||||
return bits / Byte.SIZE;
|
||||
}
|
||||
|
||||
public static VarHandle makeSegmentViewVarHandle(ValueLayout layout) {
|
||||
final class VarHandleCache {
|
||||
private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>();
|
||||
|
@ -177,7 +169,7 @@ public final class Utils {
|
|||
public static void checkElementAlignment(ValueLayout layout, String msg) {
|
||||
// Fast-path: if both size and alignment are powers of two, we can just
|
||||
// check if one is greater than the other.
|
||||
assert isPowerOfTwo(layout.bitSize());
|
||||
assert isPowerOfTwo(layout.byteSize());
|
||||
if (layout.byteAlignment() > layout.byteSize()) {
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
@ -236,14 +228,14 @@ public final class Utils {
|
|||
List<MemoryLayout> layouts = new ArrayList<>();
|
||||
long align = 0;
|
||||
for (MemoryLayout l : elements) {
|
||||
long padding = computePadding(offset, l.bitAlignment());
|
||||
long padding = computePadding(offset, l.byteAlignment());
|
||||
if (padding != 0) {
|
||||
layouts.add(MemoryLayout.paddingLayout(padding));
|
||||
offset += padding;
|
||||
}
|
||||
layouts.add(l);
|
||||
align = Math.max(align, l.bitAlignment());
|
||||
offset += l.bitSize();
|
||||
align = Math.max(align, l.byteAlignment());
|
||||
offset += l.byteSize();
|
||||
}
|
||||
long padding = computePadding(offset, align);
|
||||
if (padding != 0) {
|
||||
|
|
|
@ -160,7 +160,7 @@ public abstract sealed class AbstractLinker implements Linker permits LinuxAArch
|
|||
checkMemberOffset(sl, member, lastUnpaddedOffset, offset);
|
||||
checkLayoutRecursive(member);
|
||||
|
||||
offset += member.bitSize();
|
||||
offset += member.byteSize();
|
||||
if (!(member instanceof PaddingLayout)) {
|
||||
lastUnpaddedOffset = offset;
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ public abstract sealed class AbstractLinker implements Linker permits LinuxAArch
|
|||
for (MemoryLayout member : ul.memberLayouts()) {
|
||||
checkLayoutRecursive(member);
|
||||
if (!(member instanceof PaddingLayout)) {
|
||||
maxUnpaddedLayout = Long.max(maxUnpaddedLayout, member.bitSize());
|
||||
maxUnpaddedLayout = Long.max(maxUnpaddedLayout, member.byteSize());
|
||||
}
|
||||
}
|
||||
checkGroupSize(ul, maxUnpaddedLayout);
|
||||
|
@ -182,10 +182,10 @@ public abstract sealed class AbstractLinker implements Linker permits LinuxAArch
|
|||
|
||||
// check for trailing padding
|
||||
private static void checkGroupSize(GroupLayout gl, long maxUnpaddedOffset) {
|
||||
long expectedSize = Utils.alignUp(maxUnpaddedOffset, gl.bitAlignment());
|
||||
if (gl.bitSize() != expectedSize) {
|
||||
long expectedSize = Utils.alignUp(maxUnpaddedOffset, gl.byteAlignment());
|
||||
if (gl.byteSize() != expectedSize) {
|
||||
throw new IllegalArgumentException("Layout '" + gl + "' has unexpected size: "
|
||||
+ gl.bitSize() + " != " + expectedSize);
|
||||
+ gl.byteSize() + " != " + expectedSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ public abstract sealed class AbstractLinker implements Linker permits LinuxAArch
|
|||
// the previous layout
|
||||
private static void checkMemberOffset(StructLayout parent, MemoryLayout memberLayout,
|
||||
long lastUnpaddedOffset, long offset) {
|
||||
long expectedOffset = Utils.alignUp(lastUnpaddedOffset, memberLayout.bitAlignment());
|
||||
long expectedOffset = Utils.alignUp(lastUnpaddedOffset, memberLayout.byteAlignment());
|
||||
if (expectedOffset != offset) {
|
||||
throw new IllegalArgumentException("Member layout '" + memberLayout + "', of '" + parent + "'" +
|
||||
" found at unexpected offset: " + offset + " != " + expectedOffset);
|
||||
|
@ -202,7 +202,7 @@ public abstract sealed class AbstractLinker implements Linker permits LinuxAArch
|
|||
|
||||
private static void checkHasNaturalAlignment(MemoryLayout layout) {
|
||||
if (!((AbstractLayout<?>) layout).hasNaturalAlignment()) {
|
||||
throw new IllegalArgumentException("Layout bit alignment must be natural alignment: " + layout);
|
||||
throw new IllegalArgumentException("Layout alignment must be natural alignment: " + layout);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ public final class SharedUtils {
|
|||
public static final MethodHandle MH_CHECK_SYMBOL;
|
||||
|
||||
public static final AddressLayout C_POINTER = ADDRESS
|
||||
.withBitAlignment(64)
|
||||
.withTargetLayout(MemoryLayout.sequenceLayout(JAVA_BYTE));
|
||||
|
||||
public static final Arena DUMMY_ARENA = new Arena() {
|
||||
|
|
|
@ -58,7 +58,7 @@ public enum TypeClass {
|
|||
}
|
||||
|
||||
static boolean isRegisterAggregate(MemoryLayout type) {
|
||||
return type.bitSize() <= MAX_AGGREGATE_REGS_SIZE * 64;
|
||||
return type.byteSize() <= MAX_AGGREGATE_REGS_SIZE * 8;
|
||||
}
|
||||
|
||||
static List<MemoryLayout> scalarLayouts(GroupLayout gl) {
|
||||
|
@ -106,8 +106,8 @@ public enum TypeClass {
|
|||
return false;
|
||||
|
||||
TypeClass argClass = classifyValueType((ValueLayout) elem);
|
||||
if (elem.bitSize() != baseType.bitSize() ||
|
||||
elem.bitAlignment() != baseType.bitAlignment() ||
|
||||
if (elem.byteSize() != baseType.byteSize() ||
|
||||
elem.byteAlignment() != baseType.byteAlignment() ||
|
||||
baseArgClass != argClass) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -58,9 +58,9 @@ import static java.lang.foreign.ValueLayout.JAVA_SHORT;
|
|||
* } ffi_type;
|
||||
*/
|
||||
class FFIType {
|
||||
private static final ValueLayout SIZE_T = switch ((int) ADDRESS.bitSize()) {
|
||||
case 64 -> JAVA_LONG;
|
||||
case 32 -> JAVA_INT;
|
||||
private static final ValueLayout SIZE_T = switch ((int) ADDRESS.byteSize()) {
|
||||
case 8 -> JAVA_LONG;
|
||||
case 4 -> JAVA_INT;
|
||||
default -> throw new IllegalStateException("Address size not supported: " + ADDRESS.byteSize());
|
||||
};
|
||||
private static final ValueLayout UNSIGNED_SHORT = JAVA_SHORT;
|
||||
|
|
|
@ -181,7 +181,7 @@ public enum TypeClass {
|
|||
}
|
||||
|
||||
private static boolean isRegisterAggregate(MemoryLayout type) {
|
||||
return type.bitSize() <= MAX_AGGREGATE_REGS_SIZE * 64;
|
||||
return type.byteSize() <= MAX_AGGREGATE_REGS_SIZE * 8;
|
||||
}
|
||||
|
||||
private static TypeClass classifyStructType(GroupLayout layout) {
|
||||
|
|
|
@ -29,7 +29,6 @@ import java.lang.foreign.MemoryLayout;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -49,13 +48,13 @@ public sealed abstract class AbstractGroupLayout<L extends AbstractGroupLayout<L
|
|||
|
||||
private final Kind kind;
|
||||
private final List<MemoryLayout> elements;
|
||||
final long minBitAlignment;
|
||||
final long minByteAlignment;
|
||||
|
||||
AbstractGroupLayout(Kind kind, List<MemoryLayout> elements, long bitSize, long bitAlignment, long minBitAlignment, Optional<String> name) {
|
||||
super(bitSize, bitAlignment, name); // Subclassing creates toctou problems here
|
||||
AbstractGroupLayout(Kind kind, List<MemoryLayout> elements, long byteSize, long byteAlignment, long minByteAlignment, Optional<String> name) {
|
||||
super(byteSize, byteAlignment, name); // Subclassing creates toctou problems here
|
||||
this.kind = kind;
|
||||
this.elements = List.copyOf(elements);
|
||||
this.minBitAlignment = minBitAlignment;
|
||||
this.minByteAlignment = minByteAlignment;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,11 +81,11 @@ public sealed abstract class AbstractGroupLayout<L extends AbstractGroupLayout<L
|
|||
}
|
||||
|
||||
@Override
|
||||
public L withBitAlignment(long bitAlignment) {
|
||||
if (bitAlignment < minBitAlignment) {
|
||||
public L withByteAlignment(long byteAlignment) {
|
||||
if (byteAlignment < minByteAlignment) {
|
||||
throw new IllegalArgumentException("Invalid alignment constraint");
|
||||
}
|
||||
return super.withBitAlignment(bitAlignment);
|
||||
return super.withByteAlignment(byteAlignment);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,7 +110,7 @@ public sealed abstract class AbstractGroupLayout<L extends AbstractGroupLayout<L
|
|||
|
||||
@Override
|
||||
public final boolean hasNaturalAlignment() {
|
||||
return bitAlignment() == minBitAlignment;
|
||||
return byteAlignment() == minByteAlignment;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,30 +43,26 @@ public abstract sealed class AbstractLayout<L extends AbstractLayout<L> & Memory
|
|||
private final long byteAlignment;
|
||||
private final Optional<String> name;
|
||||
|
||||
AbstractLayout(long bitSize, long bitAlignment, Optional<String> name) {
|
||||
this.byteSize = MemoryLayoutUtil.requireBitSizeValid(bitSize, true) / 8;
|
||||
this.byteAlignment = requirePowerOfTwoAndGreaterOrEqualToEight(bitAlignment) / 8;
|
||||
AbstractLayout(long byteSize, long byteAlignment, Optional<String> name) {
|
||||
this.byteSize = MemoryLayoutUtil.requireByteSizeValid(byteSize, true);
|
||||
this.byteAlignment = requirePowerOfTwoAndGreaterOrEqualToOne(byteAlignment);
|
||||
this.name = Objects.requireNonNull(name);
|
||||
}
|
||||
|
||||
public final L withName(String name) {
|
||||
return dup(bitAlignment(), Optional.of(name));
|
||||
return dup(byteAlignment(), Optional.of(name));
|
||||
}
|
||||
|
||||
public final L withoutName() {
|
||||
return dup(bitAlignment(), Optional.empty());
|
||||
return dup(byteAlignment(), Optional.empty());
|
||||
}
|
||||
|
||||
public final Optional<String> name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public L withBitAlignment(long bitAlignment) {
|
||||
return dup(bitAlignment, name);
|
||||
}
|
||||
|
||||
public final long bitAlignment() {
|
||||
return byteAlignment * 8;
|
||||
public L withByteAlignment(long byteAlignment) {
|
||||
return dup(byteAlignment, name);
|
||||
}
|
||||
|
||||
public final long byteAlignment() {
|
||||
|
@ -77,10 +73,6 @@ public abstract sealed class AbstractLayout<L extends AbstractLayout<L> & Memory
|
|||
return byteSize;
|
||||
}
|
||||
|
||||
public final long bitSize() {
|
||||
return byteSize * 8;
|
||||
}
|
||||
|
||||
public boolean hasNaturalAlignment() {
|
||||
return byteSize == byteAlignment;
|
||||
}
|
||||
|
@ -127,21 +119,21 @@ public abstract sealed class AbstractLayout<L extends AbstractLayout<L> & Memory
|
|||
@Override
|
||||
public abstract String toString();
|
||||
|
||||
abstract L dup(long bitAlignment, Optional<String> name);
|
||||
abstract L dup(long byteAlignment, Optional<String> name);
|
||||
|
||||
String decorateLayoutString(String s) {
|
||||
if (name().isPresent()) {
|
||||
s = String.format("%s(%s)", s, name().get());
|
||||
}
|
||||
if (!hasNaturalAlignment()) {
|
||||
s = bitAlignment() + "%" + s;
|
||||
s = byteAlignment() + "%" + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private static long requirePowerOfTwoAndGreaterOrEqualToEight(long value) {
|
||||
private static long requirePowerOfTwoAndGreaterOrEqualToOne(long value) {
|
||||
if (!Utils.isPowerOfTwo(value) || // value must be a power of two
|
||||
value < 8) { // value must be greater or equal to 8
|
||||
value < 1) { // value must be greater or equal to 1
|
||||
throw new IllegalArgumentException("Invalid alignment: " + value);
|
||||
}
|
||||
return value;
|
||||
|
|
|
@ -37,11 +37,11 @@ public final class MemoryLayoutUtil {
|
|||
return value;
|
||||
}
|
||||
|
||||
public static long requireBitSizeValid(long bitSize, boolean allowZero) {
|
||||
if ((bitSize == 0 && !allowZero) || bitSize < 0 || bitSize % 8 != 0) {
|
||||
throw new IllegalArgumentException("Invalid bitSize: " + bitSize);
|
||||
public static long requireByteSizeValid(long byteSize, boolean allowZero) {
|
||||
if ((byteSize == 0 && !allowZero) || byteSize < 0) {
|
||||
throw new IllegalArgumentException("Invalid byte size: " + byteSize);
|
||||
}
|
||||
return bitSize;
|
||||
return byteSize;
|
||||
}
|
||||
|
||||
}
|
|
@ -31,17 +31,17 @@ import java.util.Optional;
|
|||
|
||||
public final class PaddingLayoutImpl extends AbstractLayout<PaddingLayoutImpl> implements PaddingLayout {
|
||||
|
||||
private PaddingLayoutImpl(long bitSize) {
|
||||
this(bitSize, 8, Optional.empty());
|
||||
private PaddingLayoutImpl(long byteSize) {
|
||||
this(byteSize, 1, Optional.empty());
|
||||
}
|
||||
|
||||
private PaddingLayoutImpl(long bitSize, long bitAlignment, Optional<String> name) {
|
||||
super(bitSize, bitAlignment, name);
|
||||
private PaddingLayoutImpl(long byteSize, long byteAlignment, Optional<String> name) {
|
||||
super(byteSize, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return decorateLayoutString("x" + bitSize());
|
||||
return decorateLayoutString("x" + byteSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,17 +49,17 @@ public final class PaddingLayoutImpl extends AbstractLayout<PaddingLayoutImpl> i
|
|||
return this == other ||
|
||||
other instanceof PaddingLayoutImpl otherPadding &&
|
||||
super.equals(other) &&
|
||||
bitSize() == otherPadding.bitSize();
|
||||
byteSize() == otherPadding.byteSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), bitSize());
|
||||
return Objects.hash(super.hashCode(), byteSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
PaddingLayoutImpl dup(long bitAlignment, Optional<String> name) {
|
||||
return new PaddingLayoutImpl(bitSize(), bitAlignment, name);
|
||||
PaddingLayoutImpl dup(long byteAlignment, Optional<String> name) {
|
||||
return new PaddingLayoutImpl(byteSize(), byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,8 +67,8 @@ public final class PaddingLayoutImpl extends AbstractLayout<PaddingLayoutImpl> i
|
|||
return true;
|
||||
}
|
||||
|
||||
public static PaddingLayout of(long bitSize) {
|
||||
return new PaddingLayoutImpl(bitSize);
|
||||
public static PaddingLayout of(long byteSize) {
|
||||
return new PaddingLayoutImpl(byteSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,11 +36,11 @@ public final class SequenceLayoutImpl extends AbstractLayout<SequenceLayoutImpl>
|
|||
private final MemoryLayout elementLayout;
|
||||
|
||||
private SequenceLayoutImpl(long elemCount, MemoryLayout elementLayout) {
|
||||
this(elemCount, elementLayout, elementLayout.bitAlignment(), Optional.empty());
|
||||
this(elemCount, elementLayout, elementLayout.byteAlignment(), Optional.empty());
|
||||
}
|
||||
|
||||
private SequenceLayoutImpl(long elemCount, MemoryLayout elementLayout, long bitAlignment, Optional<String> name) {
|
||||
super(Math.multiplyExact(elemCount, elementLayout.bitSize()), bitAlignment, name);
|
||||
private SequenceLayoutImpl(long elemCount, MemoryLayout elementLayout, long byteAlignment, Optional<String> name) {
|
||||
super(Math.multiplyExact(elemCount, elementLayout.byteSize()), byteAlignment, name);
|
||||
this.elemCount = elemCount;
|
||||
this.elementLayout = elementLayout;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ public final class SequenceLayoutImpl extends AbstractLayout<SequenceLayoutImpl>
|
|||
* @throws IllegalArgumentException if {@code elementCount < 0}.
|
||||
*/
|
||||
public SequenceLayout withElementCount(long elementCount) {
|
||||
return new SequenceLayoutImpl(elementCount, elementLayout, bitAlignment(), name());
|
||||
return new SequenceLayoutImpl(elementCount, elementLayout, byteAlignment(), name());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,7 +176,7 @@ public final class SequenceLayoutImpl extends AbstractLayout<SequenceLayoutImpl>
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
boolean max = (Long.MAX_VALUE / elementLayout.bitSize()) == elemCount;
|
||||
boolean max = (Long.MAX_VALUE / elementLayout.byteSize()) == elemCount;
|
||||
return decorateLayoutString(String.format("[%s:%s]",
|
||||
max ? "*" : elemCount, elementLayout));
|
||||
}
|
||||
|
@ -196,21 +196,21 @@ public final class SequenceLayoutImpl extends AbstractLayout<SequenceLayoutImpl>
|
|||
}
|
||||
|
||||
@Override
|
||||
SequenceLayoutImpl dup(long bitAlignment, Optional<String> name) {
|
||||
return new SequenceLayoutImpl(elementCount(), elementLayout, bitAlignment, name);
|
||||
SequenceLayoutImpl dup(long byteAlignment, Optional<String> name) {
|
||||
return new SequenceLayoutImpl(elementCount(), elementLayout, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SequenceLayoutImpl withBitAlignment(long bitAlignment) {
|
||||
if (bitAlignment < elementLayout.bitAlignment()) {
|
||||
public SequenceLayoutImpl withByteAlignment(long byteAlignment) {
|
||||
if (byteAlignment < elementLayout.byteAlignment()) {
|
||||
throw new IllegalArgumentException("Invalid alignment constraint");
|
||||
}
|
||||
return super.withBitAlignment(bitAlignment);
|
||||
return super.withByteAlignment(byteAlignment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNaturalAlignment() {
|
||||
return bitAlignment() == elementLayout.bitAlignment();
|
||||
return byteAlignment() == elementLayout.byteAlignment();
|
||||
}
|
||||
|
||||
public static SequenceLayout of(long elementCount, MemoryLayout elementLayout) {
|
||||
|
|
|
@ -32,24 +32,24 @@ import java.util.Optional;
|
|||
|
||||
public final class StructLayoutImpl extends AbstractGroupLayout<StructLayoutImpl> implements StructLayout {
|
||||
|
||||
private StructLayoutImpl(List<MemoryLayout> elements, long bitSize, long bitAlignment, long minBitAlignment, Optional<String> name) {
|
||||
super(Kind.STRUCT, elements, bitSize, bitAlignment, minBitAlignment, name);
|
||||
private StructLayoutImpl(List<MemoryLayout> elements, long byteSize, long byteAlignment, long minByteAlignment, Optional<String> name) {
|
||||
super(Kind.STRUCT, elements, byteSize, byteAlignment, minByteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
StructLayoutImpl dup(long bitAlignment, Optional<String> name) {
|
||||
return new StructLayoutImpl(memberLayouts(), bitSize(), bitAlignment, minBitAlignment, name);
|
||||
StructLayoutImpl dup(long byteAlignment, Optional<String> name) {
|
||||
return new StructLayoutImpl(memberLayouts(), byteSize(), byteAlignment, minByteAlignment, name);
|
||||
}
|
||||
|
||||
public static StructLayout of(List<MemoryLayout> elements) {
|
||||
long size = 0;
|
||||
long align = 8;
|
||||
long align = 1;
|
||||
for (MemoryLayout elem : elements) {
|
||||
if (size % elem.bitAlignment() != 0) {
|
||||
if (size % elem.byteAlignment() != 0) {
|
||||
throw new IllegalArgumentException("Invalid alignment constraint for member layout: " + elem);
|
||||
}
|
||||
size = Math.addExact(size, elem.bitSize());
|
||||
align = Math.max(align, elem.bitAlignment());
|
||||
size = Math.addExact(size, elem.byteSize());
|
||||
align = Math.max(align, elem.byteAlignment());
|
||||
}
|
||||
return new StructLayoutImpl(elements, size, align, align, Optional.empty());
|
||||
}
|
||||
|
|
|
@ -32,21 +32,21 @@ import java.util.Optional;
|
|||
|
||||
public final class UnionLayoutImpl extends AbstractGroupLayout<UnionLayoutImpl> implements UnionLayout {
|
||||
|
||||
private UnionLayoutImpl(List<MemoryLayout> elements, long bitSize, long bitAlignment, long minBitAlignment, Optional<String> name) {
|
||||
super(Kind.UNION, elements, bitSize, bitAlignment, minBitAlignment, name);
|
||||
private UnionLayoutImpl(List<MemoryLayout> elements, long byteSize, long byteAlignment, long minByteAlignment, Optional<String> name) {
|
||||
super(Kind.UNION, elements, byteSize, byteAlignment, minByteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
UnionLayoutImpl dup(long bitAlignment, Optional<String> name) {
|
||||
return new UnionLayoutImpl(memberLayouts(), bitSize(), bitAlignment, minBitAlignment, name);
|
||||
UnionLayoutImpl dup(long byteAlignment, Optional<String> name) {
|
||||
return new UnionLayoutImpl(memberLayouts(), byteSize(), byteAlignment, minByteAlignment, name);
|
||||
}
|
||||
|
||||
public static UnionLayout of(List<MemoryLayout> elements) {
|
||||
long size = 0;
|
||||
long align = 8;
|
||||
long align = 1;
|
||||
for (MemoryLayout elem : elements) {
|
||||
size = Math.max(size, elem.bitSize());
|
||||
align = Math.max(align, elem.bitAlignment());
|
||||
size = Math.max(size, elem.byteSize());
|
||||
align = Math.max(align, elem.byteAlignment());
|
||||
}
|
||||
return new UnionLayoutImpl(elements, size, align, align, Optional.empty());
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ import java.util.Optional;
|
|||
|
||||
/**
|
||||
* A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as <em>integral</em> types
|
||||
* (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size, an alignment (in bits),
|
||||
* (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size, an alignment (expressed in bytes),
|
||||
* a {@linkplain ByteOrder byte order}, and a <em>carrier</em>, that is, the Java type that should be used when
|
||||
* {@linkplain MemorySegment#get(ValueLayout.OfInt, long) accessing} a memory region using the value layout.
|
||||
* <p>
|
||||
|
@ -64,18 +64,18 @@ public final class ValueLayouts {
|
|||
|
||||
abstract sealed static class AbstractValueLayout<V extends AbstractValueLayout<V> & ValueLayout> extends AbstractLayout<V> {
|
||||
|
||||
static final int ADDRESS_SIZE_BITS = Unsafe.ADDRESS_SIZE * 8;
|
||||
static final int ADDRESS_SIZE_BYTES = Unsafe.ADDRESS_SIZE;
|
||||
|
||||
private final Class<?> carrier;
|
||||
private final ByteOrder order;
|
||||
@Stable
|
||||
private VarHandle handle;
|
||||
|
||||
AbstractValueLayout(Class<?> carrier, ByteOrder order, long bitSize, long bitAlignment, Optional<String> name) {
|
||||
super(bitSize, bitAlignment, name);
|
||||
AbstractValueLayout(Class<?> carrier, ByteOrder order, long byteSize, long byteAlignment, Optional<String> name) {
|
||||
super(byteSize, byteAlignment, name);
|
||||
this.carrier = carrier;
|
||||
this.order = order;
|
||||
assertCarrierSize(carrier, bitSize);
|
||||
assertCarrierSize(carrier, byteSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,7 +94,7 @@ public final class ValueLayouts {
|
|||
*/
|
||||
public final V withOrder(ByteOrder order) {
|
||||
Objects.requireNonNull(order);
|
||||
return dup(order, bitAlignment(), name());
|
||||
return dup(order, byteAlignment(), name());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -103,7 +103,7 @@ public final class ValueLayouts {
|
|||
if (order == ByteOrder.LITTLE_ENDIAN) {
|
||||
descriptor = Character.toLowerCase(descriptor);
|
||||
}
|
||||
return decorateLayoutString(String.format("%s%d", descriptor, bitSize()));
|
||||
return decorateLayoutString(String.format("%s%d", descriptor, byteSize()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -143,20 +143,21 @@ public final class ValueLayouts {
|
|||
}
|
||||
|
||||
@Override
|
||||
final V dup(long bitAlignment, Optional<String> name) {
|
||||
return dup(order(), bitAlignment, name);
|
||||
final V dup(long byteAlignment, Optional<String> name) {
|
||||
return dup(order(), byteAlignment, name);
|
||||
}
|
||||
|
||||
abstract V dup(ByteOrder order, long bitAlignment, Optional<String> name);
|
||||
abstract V dup(ByteOrder order, long byteAlignment, Optional<String> name);
|
||||
|
||||
static void assertCarrierSize(Class<?> carrier, long bitSize) {
|
||||
static void assertCarrierSize(Class<?> carrier, long byteSize) {
|
||||
assert isValidCarrier(carrier);
|
||||
assert carrier != MemorySegment.class
|
||||
// MemorySegment bitSize must always equal ADDRESS_SIZE_BITS
|
||||
|| bitSize == ADDRESS_SIZE_BITS;
|
||||
// MemorySegment byteSize must always equal ADDRESS_SIZE_BYTES
|
||||
|| byteSize == ADDRESS_SIZE_BYTES;
|
||||
assert !carrier.isPrimitive() ||
|
||||
// Primitive class bitSize must always correspond
|
||||
bitSize == (carrier == boolean.class ? 8 : Wrapper.forPrimitiveType(carrier).bitWidth());
|
||||
// Primitive class byteSize must always correspond
|
||||
byteSize == (carrier == boolean.class ? 1 :
|
||||
Utils.byteWidthOfPrimitive(carrier));
|
||||
}
|
||||
|
||||
static boolean isValidCarrier(Class<?> carrier) {
|
||||
|
@ -189,129 +190,129 @@ public final class ValueLayouts {
|
|||
|
||||
public static final class OfBooleanImpl extends AbstractValueLayout<OfBooleanImpl> implements ValueLayout.OfBoolean {
|
||||
|
||||
private OfBooleanImpl(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
super(boolean.class, order, Byte.SIZE, bitAlignment, name);
|
||||
private OfBooleanImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
super(boolean.class, order, Byte.BYTES, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfBooleanImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfBooleanImpl(order, bitAlignment, name);
|
||||
OfBooleanImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfBooleanImpl(order, byteAlignment, name);
|
||||
}
|
||||
|
||||
public static OfBoolean of(ByteOrder order) {
|
||||
return new OfBooleanImpl(order, Byte.SIZE, Optional.empty());
|
||||
return new OfBooleanImpl(order, Byte.BYTES, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OfByteImpl extends AbstractValueLayout<OfByteImpl> implements ValueLayout.OfByte {
|
||||
|
||||
private OfByteImpl(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
super(byte.class, order, Byte.SIZE, bitAlignment, name);
|
||||
private OfByteImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
super(byte.class, order, Byte.BYTES, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfByteImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfByteImpl(order, bitAlignment, name);
|
||||
OfByteImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfByteImpl(order, byteAlignment, name);
|
||||
}
|
||||
|
||||
public static OfByte of(ByteOrder order) {
|
||||
return new OfByteImpl(order, Byte.SIZE, Optional.empty());
|
||||
return new OfByteImpl(order, Byte.BYTES, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OfCharImpl extends AbstractValueLayout<OfCharImpl> implements ValueLayout.OfChar {
|
||||
|
||||
private OfCharImpl(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
super(char.class, order, Character.SIZE, bitAlignment, name);
|
||||
private OfCharImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
super(char.class, order, Character.BYTES, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfCharImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfCharImpl(order, bitAlignment, name);
|
||||
OfCharImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfCharImpl(order, byteAlignment, name);
|
||||
}
|
||||
|
||||
public static OfChar of(ByteOrder order) {
|
||||
return new OfCharImpl(order, Character.SIZE, Optional.empty());
|
||||
return new OfCharImpl(order, Character.BYTES, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OfShortImpl extends AbstractValueLayout<OfShortImpl> implements ValueLayout.OfShort {
|
||||
|
||||
private OfShortImpl(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
super(short.class, order, Short.SIZE, bitAlignment, name);
|
||||
private OfShortImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
super(short.class, order, Short.BYTES, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfShortImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfShortImpl(order, bitAlignment, name);
|
||||
OfShortImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfShortImpl(order, byteAlignment, name);
|
||||
}
|
||||
|
||||
public static OfShort of(ByteOrder order) {
|
||||
return new OfShortImpl(order, Short.SIZE, Optional.empty());
|
||||
return new OfShortImpl(order, Short.BYTES, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OfIntImpl extends AbstractValueLayout<OfIntImpl> implements ValueLayout.OfInt {
|
||||
|
||||
private OfIntImpl(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
super(int.class, order, Integer.SIZE, bitAlignment, name);
|
||||
private OfIntImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
super(int.class, order, Integer.BYTES, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfIntImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfIntImpl(order, bitAlignment, name);
|
||||
OfIntImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfIntImpl(order, byteAlignment, name);
|
||||
}
|
||||
|
||||
public static OfInt of(ByteOrder order) {
|
||||
return new OfIntImpl(order, Integer.SIZE, Optional.empty());
|
||||
return new OfIntImpl(order, Integer.BYTES, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OfFloatImpl extends AbstractValueLayout<OfFloatImpl> implements ValueLayout.OfFloat {
|
||||
|
||||
private OfFloatImpl(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
super(float.class, order, Float.SIZE, bitAlignment, name);
|
||||
private OfFloatImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
super(float.class, order, Float.BYTES, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfFloatImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfFloatImpl(order, bitAlignment, name);
|
||||
OfFloatImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfFloatImpl(order, byteAlignment, name);
|
||||
}
|
||||
|
||||
public static OfFloat of(ByteOrder order) {
|
||||
return new OfFloatImpl(order, Float.SIZE, Optional.empty());
|
||||
return new OfFloatImpl(order, Float.BYTES, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OfLongImpl extends AbstractValueLayout<OfLongImpl> implements ValueLayout.OfLong {
|
||||
|
||||
private OfLongImpl(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
super(long.class, order, Long.SIZE, bitAlignment, name);
|
||||
private OfLongImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
super(long.class, order, Long.BYTES, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfLongImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfLongImpl(order, bitAlignment, name);
|
||||
OfLongImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfLongImpl(order, byteAlignment, name);
|
||||
}
|
||||
|
||||
public static OfLong of(ByteOrder order) {
|
||||
return new OfLongImpl(order, ADDRESS_SIZE_BITS, Optional.empty());
|
||||
return new OfLongImpl(order, ADDRESS_SIZE_BYTES, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OfDoubleImpl extends AbstractValueLayout<OfDoubleImpl> implements ValueLayout.OfDouble {
|
||||
|
||||
private OfDoubleImpl(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
super(double.class, order, Double.SIZE, bitAlignment, name);
|
||||
private OfDoubleImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
super(double.class, order, Double.BYTES, byteAlignment, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
OfDoubleImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfDoubleImpl(order, bitAlignment, name);
|
||||
OfDoubleImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfDoubleImpl(order, byteAlignment, name);
|
||||
}
|
||||
|
||||
public static OfDouble of(ByteOrder order) {
|
||||
return new OfDoubleImpl(order, ADDRESS_SIZE_BITS, Optional.empty());
|
||||
return new OfDoubleImpl(order, ADDRESS_SIZE_BYTES, Optional.empty());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -320,14 +321,14 @@ public final class ValueLayouts {
|
|||
|
||||
private final MemoryLayout targetLayout;
|
||||
|
||||
private OfAddressImpl(ByteOrder order, long bitSize, long bitAlignment, MemoryLayout targetLayout, Optional<String> name) {
|
||||
super(MemorySegment.class, order, bitSize, bitAlignment, name);
|
||||
private OfAddressImpl(ByteOrder order, long byteSize, long byteAlignment, MemoryLayout targetLayout, Optional<String> name) {
|
||||
super(MemorySegment.class, order, byteSize, byteAlignment, name);
|
||||
this.targetLayout = targetLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
OfAddressImpl dup(ByteOrder order, long bitAlignment, Optional<String> name) {
|
||||
return new OfAddressImpl(order, bitSize(), bitAlignment,targetLayout, name);
|
||||
OfAddressImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
|
||||
return new OfAddressImpl(order, byteSize(), byteAlignment,targetLayout, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -346,12 +347,12 @@ public final class ValueLayouts {
|
|||
public AddressLayout withTargetLayout(MemoryLayout layout) {
|
||||
Reflection.ensureNativeAccess(Reflection.getCallerClass(), AddressLayout.class, "withTargetLayout");
|
||||
Objects.requireNonNull(layout);
|
||||
return new OfAddressImpl(order(), bitSize(), bitAlignment(), layout, name());
|
||||
return new OfAddressImpl(order(), byteSize(), byteAlignment(), layout, name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressLayout withoutTargetLayout() {
|
||||
return new OfAddressImpl(order(), bitSize(), bitAlignment(), null, name());
|
||||
return new OfAddressImpl(order(), byteSize(), byteAlignment(), null, name());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -360,7 +361,7 @@ public final class ValueLayouts {
|
|||
}
|
||||
|
||||
public static AddressLayout of(ByteOrder order) {
|
||||
return new OfAddressImpl(order, ADDRESS_SIZE_BITS, ADDRESS_SIZE_BITS, null, Optional.empty());
|
||||
return new OfAddressImpl(order, ADDRESS_SIZE_BYTES, ADDRESS_SIZE_BYTES, null, Optional.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -369,7 +370,7 @@ public final class ValueLayouts {
|
|||
if (order() == ByteOrder.LITTLE_ENDIAN) {
|
||||
descriptor = Character.toLowerCase(descriptor);
|
||||
}
|
||||
String str = decorateLayoutString(String.format("%s%d", descriptor, bitSize()));
|
||||
String str = decorateLayoutString(String.format("%s%d", descriptor, byteSize()));
|
||||
if (targetLayout != null) {
|
||||
str += ":" + targetLayout;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue