14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 *
25 */
26 package jdk.internal.foreign.layout;
27
28 import jdk.internal.foreign.Utils;
29 import jdk.internal.misc.Unsafe;
30 import jdk.internal.reflect.CallerSensitive;
31 import jdk.internal.reflect.Reflection;
32 import jdk.internal.vm.annotation.ForceInline;
33 import jdk.internal.vm.annotation.Stable;
34 import sun.invoke.util.Wrapper;
35
36 import java.lang.foreign.MemoryLayout;
37 import java.lang.foreign.MemorySegment;
38 import java.lang.foreign.AddressLayout;
39 import java.lang.foreign.ValueLayout;
40 import java.lang.invoke.VarHandle;
41 import java.nio.ByteOrder;
42 import java.util.ArrayList;
43 import java.util.List;
44 import java.util.Objects;
45 import java.util.Optional;
46
47 /**
48 * 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
49 * (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size, an alignment (expressed in bytes),
50 * a {@linkplain ByteOrder byte order}, and a <em>carrier</em>, that is, the Java type that should be used when
51 * {@linkplain MemorySegment#get(ValueLayout.OfInt, long) accessing} a memory region using the value layout.
52 * <p>
53 * This class defines useful value layout constants for Java primitive types and addresses.
54 * The layout constants in this class make implicit alignment and byte-ordering assumption: all layout
55 * constants in this class are byte-aligned, and their byte order is set to the {@linkplain ByteOrder#nativeOrder() platform default},
56 * thus making it easy to work with other APIs, such as arrays and {@link java.nio.ByteBuffer}.
57 *
58 * @implSpec This class and its subclasses are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
59 */
60 public final class ValueLayouts {
61
62 // Suppresses default constructor, ensuring non-instantiability.
63 private ValueLayouts() {}
98 }
99
100 @Override
101 public String toString() {
102 char descriptor = carrier.descriptorString().charAt(0);
103 if (order == ByteOrder.LITTLE_ENDIAN) {
104 descriptor = Character.toLowerCase(descriptor);
105 }
106 return decorateLayoutString(String.format("%s%d", descriptor, byteSize()));
107 }
108
109 @Override
110 public boolean equals(Object other) {
111 return this == other ||
112 other instanceof AbstractValueLayout<?> otherValue &&
113 super.equals(other) &&
114 carrier.equals(otherValue.carrier) &&
115 order.equals(otherValue.order);
116 }
117
118 public final VarHandle arrayElementVarHandle(int... shape) {
119 Objects.requireNonNull(shape);
120 if (!Utils.isElementAligned((ValueLayout) this)) {
121 throw new UnsupportedOperationException("Layout alignment greater than its size");
122 }
123 MemoryLayout layout = self();
124 List<MemoryLayout.PathElement> path = new ArrayList<>();
125 for (int i = shape.length; i > 0; i--) {
126 int size = shape[i - 1];
127 if (size < 0) throw new IllegalArgumentException("Invalid shape size: " + size);
128 layout = MemoryLayout.sequenceLayout(size, layout);
129 path.add(MemoryLayout.PathElement.sequenceElement());
130 }
131 layout = MemoryLayout.sequenceLayout(layout);
132 path.add(MemoryLayout.PathElement.sequenceElement());
133 return layout.varHandle(path.toArray(new MemoryLayout.PathElement[0]));
134 }
135
136 /**
137 * {@return the carrier associated with this value layout}
138 */
139 public final Class<?> carrier() {
140 return carrier;
141 }
142
143 @Override
144 public int hashCode() {
145 return Objects.hash(super.hashCode(), order, carrier);
146 }
147
148 @Override
149 final V dup(long byteAlignment, Optional<String> name) {
150 return dup(order(), byteAlignment, name);
151 }
152
153 abstract V dup(ByteOrder order, long byteAlignment, Optional<String> name);
154
155 static void assertCarrierSize(Class<?> carrier, long byteSize) {
160 assert !carrier.isPrimitive() ||
161 // Primitive class byteSize must always correspond
162 byteSize == (carrier == boolean.class ? 1 :
163 Utils.byteWidthOfPrimitive(carrier));
164 }
165
166 static boolean isValidCarrier(Class<?> carrier) {
167 // void.class is not valid
168 return carrier == boolean.class
169 || carrier == byte.class
170 || carrier == short.class
171 || carrier == char.class
172 || carrier == int.class
173 || carrier == long.class
174 || carrier == float.class
175 || carrier == double.class
176 || carrier == MemorySegment.class;
177 }
178
179 @ForceInline
180 public final VarHandle accessHandle() {
181 if (handle == null) {
182 // this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity
183 handle = Utils.makeSegmentViewVarHandle(self());
184 }
185 return handle;
186 }
187
188 @SuppressWarnings("unchecked")
189 final V self() {
190 return (V) this;
191 }
192 }
193
194 public static final class OfBooleanImpl extends AbstractValueLayout<OfBooleanImpl> implements ValueLayout.OfBoolean {
195
196 private OfBooleanImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
197 super(boolean.class, order, Byte.BYTES, byteAlignment, name);
198 }
199
200 @Override
376 String str = decorateLayoutString(String.format("%s%d", descriptor, byteSize()));
377 if (targetLayout != null) {
378 str += ":" + targetLayout;
379 }
380 return str;
381 }
382 }
383
384 /**
385 * Creates a value layout of given Java carrier and byte order. The type of resulting value layout is determined
386 * by the carrier provided:
387 * <ul>
388 * <li>{@link ValueLayout.OfBoolean}, for {@code boolean.class}</li>
389 * <li>{@link ValueLayout.OfByte}, for {@code byte.class}</li>
390 * <li>{@link ValueLayout.OfShort}, for {@code short.class}</li>
391 * <li>{@link ValueLayout.OfChar}, for {@code char.class}</li>
392 * <li>{@link ValueLayout.OfInt}, for {@code int.class}</li>
393 * <li>{@link ValueLayout.OfFloat}, for {@code float.class}</li>
394 * <li>{@link ValueLayout.OfLong}, for {@code long.class}</li>
395 * <li>{@link ValueLayout.OfDouble}, for {@code double.class}</li>
396 * <li>{@link ValueLayout.OfAddress}, for {@code MemorySegment.class}</li>
397 * </ul>
398 * @param carrier the value layout carrier.
399 * @param order the value layout's byte order.
400 * @return a value layout with the given Java carrier and byte-order.
401 * @throws IllegalArgumentException if the carrier type is not supported.
402 */
403 public static ValueLayout valueLayout(Class<?> carrier, ByteOrder order) {
404 Objects.requireNonNull(carrier);
405 Objects.requireNonNull(order);
406 if (carrier == boolean.class) {
407 return ValueLayouts.OfBooleanImpl.of(order);
408 } else if (carrier == char.class) {
409 return ValueLayouts.OfCharImpl.of(order);
410 } else if (carrier == byte.class) {
411 return ValueLayouts.OfByteImpl.of(order);
412 } else if (carrier == short.class) {
413 return ValueLayouts.OfShortImpl.of(order);
414 } else if (carrier == int.class) {
415 return ValueLayouts.OfIntImpl.of(order);
416 } else if (carrier == float.class) {
|
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 *
25 */
26 package jdk.internal.foreign.layout;
27
28 import jdk.internal.foreign.Utils;
29 import jdk.internal.misc.Unsafe;
30 import jdk.internal.reflect.CallerSensitive;
31 import jdk.internal.reflect.Reflection;
32 import jdk.internal.vm.annotation.ForceInline;
33 import jdk.internal.vm.annotation.Stable;
34
35 import java.lang.foreign.AddressLayout;
36 import java.lang.foreign.MemoryLayout;
37 import java.lang.foreign.MemorySegment;
38 import java.lang.foreign.ValueLayout;
39 import java.lang.invoke.VarHandle;
40 import java.nio.ByteOrder;
41 import java.util.Objects;
42 import java.util.Optional;
43
44 /**
45 * 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
46 * (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size, an alignment (expressed in bytes),
47 * a {@linkplain ByteOrder byte order}, and a <em>carrier</em>, that is, the Java type that should be used when
48 * {@linkplain MemorySegment#get(ValueLayout.OfInt, long) accessing} a memory region using the value layout.
49 * <p>
50 * This class defines useful value layout constants for Java primitive types and addresses.
51 * The layout constants in this class make implicit alignment and byte-ordering assumption: all layout
52 * constants in this class are byte-aligned, and their byte order is set to the {@linkplain ByteOrder#nativeOrder() platform default},
53 * thus making it easy to work with other APIs, such as arrays and {@link java.nio.ByteBuffer}.
54 *
55 * @implSpec This class and its subclasses are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
56 */
57 public final class ValueLayouts {
58
59 // Suppresses default constructor, ensuring non-instantiability.
60 private ValueLayouts() {}
95 }
96
97 @Override
98 public String toString() {
99 char descriptor = carrier.descriptorString().charAt(0);
100 if (order == ByteOrder.LITTLE_ENDIAN) {
101 descriptor = Character.toLowerCase(descriptor);
102 }
103 return decorateLayoutString(String.format("%s%d", descriptor, byteSize()));
104 }
105
106 @Override
107 public boolean equals(Object other) {
108 return this == other ||
109 other instanceof AbstractValueLayout<?> otherValue &&
110 super.equals(other) &&
111 carrier.equals(otherValue.carrier) &&
112 order.equals(otherValue.order);
113 }
114
115 /**
116 * {@return the carrier associated with this value layout}
117 */
118 public final Class<?> carrier() {
119 return carrier;
120 }
121
122 @Override
123 public int hashCode() {
124 return Objects.hash(super.hashCode(), order, carrier);
125 }
126
127 @Override
128 final V dup(long byteAlignment, Optional<String> name) {
129 return dup(order(), byteAlignment, name);
130 }
131
132 abstract V dup(ByteOrder order, long byteAlignment, Optional<String> name);
133
134 static void assertCarrierSize(Class<?> carrier, long byteSize) {
139 assert !carrier.isPrimitive() ||
140 // Primitive class byteSize must always correspond
141 byteSize == (carrier == boolean.class ? 1 :
142 Utils.byteWidthOfPrimitive(carrier));
143 }
144
145 static boolean isValidCarrier(Class<?> carrier) {
146 // void.class is not valid
147 return carrier == boolean.class
148 || carrier == byte.class
149 || carrier == short.class
150 || carrier == char.class
151 || carrier == int.class
152 || carrier == long.class
153 || carrier == float.class
154 || carrier == double.class
155 || carrier == MemorySegment.class;
156 }
157
158 @ForceInline
159 public final VarHandle varHandle() {
160 if (handle == null) {
161 // this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity
162 handle = Utils.makeSegmentViewVarHandle(self());
163 }
164 return handle;
165 }
166
167 @SuppressWarnings("unchecked")
168 final V self() {
169 return (V) this;
170 }
171 }
172
173 public static final class OfBooleanImpl extends AbstractValueLayout<OfBooleanImpl> implements ValueLayout.OfBoolean {
174
175 private OfBooleanImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
176 super(boolean.class, order, Byte.BYTES, byteAlignment, name);
177 }
178
179 @Override
355 String str = decorateLayoutString(String.format("%s%d", descriptor, byteSize()));
356 if (targetLayout != null) {
357 str += ":" + targetLayout;
358 }
359 return str;
360 }
361 }
362
363 /**
364 * Creates a value layout of given Java carrier and byte order. The type of resulting value layout is determined
365 * by the carrier provided:
366 * <ul>
367 * <li>{@link ValueLayout.OfBoolean}, for {@code boolean.class}</li>
368 * <li>{@link ValueLayout.OfByte}, for {@code byte.class}</li>
369 * <li>{@link ValueLayout.OfShort}, for {@code short.class}</li>
370 * <li>{@link ValueLayout.OfChar}, for {@code char.class}</li>
371 * <li>{@link ValueLayout.OfInt}, for {@code int.class}</li>
372 * <li>{@link ValueLayout.OfFloat}, for {@code float.class}</li>
373 * <li>{@link ValueLayout.OfLong}, for {@code long.class}</li>
374 * <li>{@link ValueLayout.OfDouble}, for {@code double.class}</li>
375 * <li>{@link AddressLayout}, for {@code MemorySegment.class}</li>
376 * </ul>
377 * @param carrier the value layout carrier.
378 * @param order the value layout's byte order.
379 * @return a value layout with the given Java carrier and byte-order.
380 * @throws IllegalArgumentException if the carrier type is not supported.
381 */
382 public static ValueLayout valueLayout(Class<?> carrier, ByteOrder order) {
383 Objects.requireNonNull(carrier);
384 Objects.requireNonNull(order);
385 if (carrier == boolean.class) {
386 return ValueLayouts.OfBooleanImpl.of(order);
387 } else if (carrier == char.class) {
388 return ValueLayouts.OfCharImpl.of(order);
389 } else if (carrier == byte.class) {
390 return ValueLayouts.OfByteImpl.of(order);
391 } else if (carrier == short.class) {
392 return ValueLayouts.OfShortImpl.of(order);
393 } else if (carrier == int.class) {
394 return ValueLayouts.OfIntImpl.of(order);
395 } else if (carrier == float.class) {
|