1 /*
  2  *  Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
  3  *  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  *  This code is free software; you can redistribute it and/or modify it
  6  *  under the terms of the GNU General Public License version 2 only, as
  7  *  published by the Free Software Foundation.  Oracle designates this
  8  *  particular file as subject to the "Classpath" exception as provided
  9  *  by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  *  This code is distributed in the hope that it will be useful, but WITHOUT
 12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 package 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() {}
 61 
 62     abstract sealed static class AbstractValueLayout<V extends AbstractValueLayout<V> & ValueLayout> extends AbstractLayout<V> {
 63 
 64         static final int ADDRESS_SIZE_BYTES = Unsafe.ADDRESS_SIZE;
 65 
 66         private final Class<?> carrier;
 67         private final ByteOrder order;
 68         @Stable
 69         private VarHandle handle;
 70 
 71         AbstractValueLayout(Class<?> carrier, ByteOrder order, long byteSize, long byteAlignment, Optional<String> name) {
 72             super(byteSize, byteAlignment, name);
 73             this.carrier = carrier;
 74             this.order = order;
 75             assertCarrierSize(carrier, byteSize);
 76         }
 77 
 78         /**
 79          * {@return the value's byte order}
 80          */
 81         public final ByteOrder order() {
 82             return order;
 83         }
 84 
 85         /**
 86          * Returns a value layout with the same carrier, alignment constraints and name as this value layout,
 87          * but with the specified byte order.
 88          *
 89          * @param order the desired byte order.
 90          * @return a value layout with the given byte order.
 91          */
 92         public final V withOrder(ByteOrder order) {
 93             Objects.requireNonNull(order);
 94             return dup(order, byteAlignment(), name());
 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) {
135             assert isValidCarrier(carrier);
136             assert carrier != MemorySegment.class
137                     // MemorySegment byteSize must always equal ADDRESS_SIZE_BYTES
138                     || byteSize == ADDRESS_SIZE_BYTES;
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
180         OfBooleanImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
181             return new OfBooleanImpl(order, byteAlignment, name);
182         }
183 
184         public static OfBoolean of(ByteOrder order) {
185             return new OfBooleanImpl(order, Byte.BYTES, Optional.empty());
186         }
187     }
188 
189     public static final class OfByteImpl extends AbstractValueLayout<OfByteImpl> implements ValueLayout.OfByte {
190 
191         private OfByteImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
192             super(byte.class, order, Byte.BYTES, byteAlignment, name);
193         }
194 
195         @Override
196         OfByteImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
197             return new OfByteImpl(order, byteAlignment, name);
198         }
199 
200         public static OfByte of(ByteOrder order) {
201             return new OfByteImpl(order, Byte.BYTES, Optional.empty());
202         }
203     }
204 
205     public static final class OfCharImpl extends AbstractValueLayout<OfCharImpl> implements ValueLayout.OfChar {
206 
207         private OfCharImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
208             super(char.class, order, Character.BYTES, byteAlignment, name);
209         }
210 
211         @Override
212         OfCharImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
213             return new OfCharImpl(order, byteAlignment, name);
214         }
215 
216         public static OfChar of(ByteOrder order) {
217             return new OfCharImpl(order, Character.BYTES, Optional.empty());
218         }
219     }
220 
221     public static final class OfShortImpl extends AbstractValueLayout<OfShortImpl> implements ValueLayout.OfShort {
222 
223         private OfShortImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
224             super(short.class, order, Short.BYTES, byteAlignment, name);
225         }
226 
227         @Override
228         OfShortImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
229             return new OfShortImpl(order, byteAlignment, name);
230         }
231 
232         public static OfShort of(ByteOrder order) {
233             return new OfShortImpl(order, Short.BYTES, Optional.empty());
234         }
235     }
236 
237     public static final class OfIntImpl extends AbstractValueLayout<OfIntImpl> implements ValueLayout.OfInt {
238 
239         private OfIntImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
240             super(int.class, order, Integer.BYTES, byteAlignment, name);
241         }
242 
243         @Override
244         OfIntImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
245             return new OfIntImpl(order, byteAlignment, name);
246         }
247 
248         public static OfInt of(ByteOrder order) {
249             return new OfIntImpl(order, Integer.BYTES, Optional.empty());
250         }
251     }
252 
253     public static final class OfFloatImpl extends AbstractValueLayout<OfFloatImpl> implements ValueLayout.OfFloat {
254 
255         private OfFloatImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
256             super(float.class, order, Float.BYTES, byteAlignment, name);
257         }
258 
259         @Override
260         OfFloatImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
261             return new OfFloatImpl(order, byteAlignment, name);
262         }
263 
264         public static OfFloat of(ByteOrder order) {
265             return new OfFloatImpl(order, Float.BYTES, Optional.empty());
266         }
267     }
268 
269     public static final class OfLongImpl extends AbstractValueLayout<OfLongImpl> implements ValueLayout.OfLong {
270 
271         private OfLongImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
272             super(long.class, order, Long.BYTES, byteAlignment, name);
273         }
274 
275         @Override
276         OfLongImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
277             return new OfLongImpl(order, byteAlignment, name);
278         }
279 
280         public static OfLong of(ByteOrder order) {
281             return new OfLongImpl(order, ADDRESS_SIZE_BYTES, Optional.empty());
282         }
283     }
284 
285     public static final class OfDoubleImpl extends AbstractValueLayout<OfDoubleImpl> implements ValueLayout.OfDouble {
286 
287         private OfDoubleImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
288             super(double.class, order, Double.BYTES, byteAlignment, name);
289         }
290 
291         @Override
292         OfDoubleImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
293             return new OfDoubleImpl(order, byteAlignment, name);
294         }
295 
296         public static OfDouble of(ByteOrder order) {
297             return new OfDoubleImpl(order, ADDRESS_SIZE_BYTES, Optional.empty());
298         }
299 
300     }
301 
302     public static final class OfAddressImpl extends AbstractValueLayout<OfAddressImpl> implements AddressLayout {
303 
304         private final MemoryLayout targetLayout;
305 
306         private OfAddressImpl(ByteOrder order, long byteSize, long byteAlignment, MemoryLayout targetLayout, Optional<String> name) {
307             super(MemorySegment.class, order, byteSize, byteAlignment, name);
308             this.targetLayout = targetLayout;
309         }
310 
311         @Override
312         OfAddressImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
313             return new OfAddressImpl(order, byteSize(), byteAlignment,targetLayout, name);
314         }
315 
316         @Override
317         public boolean equals(Object other) {
318             return super.equals(other) &&
319                     Objects.equals(((OfAddressImpl)other).targetLayout, this.targetLayout);
320         }
321 
322         @Override
323         public int hashCode() {
324             return Objects.hash(super.hashCode(), targetLayout);
325         }
326 
327         @Override
328         @CallerSensitive
329         public AddressLayout withTargetLayout(MemoryLayout layout) {
330             Reflection.ensureNativeAccess(Reflection.getCallerClass(), AddressLayout.class, "withTargetLayout");
331             Objects.requireNonNull(layout);
332             return new OfAddressImpl(order(), byteSize(), byteAlignment(), layout, name());
333         }
334 
335         @Override
336         public AddressLayout withoutTargetLayout() {
337             return new OfAddressImpl(order(), byteSize(), byteAlignment(), null, name());
338         }
339 
340         @Override
341         public Optional<MemoryLayout> targetLayout() {
342             return Optional.ofNullable(targetLayout);
343         }
344 
345         public static AddressLayout of(ByteOrder order) {
346             return new OfAddressImpl(order, ADDRESS_SIZE_BYTES, ADDRESS_SIZE_BYTES, null, Optional.empty());
347         }
348 
349         @Override
350         public String toString() {
351             char descriptor = 'A';
352             if (order() == ByteOrder.LITTLE_ENDIAN) {
353                 descriptor = Character.toLowerCase(descriptor);
354             }
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) {
396             return ValueLayouts.OfFloatImpl.of(order);
397         } else if (carrier == long.class) {
398             return ValueLayouts.OfLongImpl.of(order);
399         } else if (carrier == double.class) {
400             return ValueLayouts.OfDoubleImpl.of(order);
401         } else if (carrier == MemorySegment.class) {
402             return ValueLayouts.OfAddressImpl.of(order);
403         } else {
404             throw new IllegalArgumentException("Unsupported carrier: " + carrier.getName());
405         }
406     }
407 }