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 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() {}
 64 
 65     abstract sealed static class AbstractValueLayout<V extends AbstractValueLayout<V> & ValueLayout> extends AbstractLayout<V> {
 66 
 67         static final int ADDRESS_SIZE_BYTES = Unsafe.ADDRESS_SIZE;
 68 
 69         private final Class<?> carrier;
 70         private final ByteOrder order;
 71         @Stable
 72         private VarHandle handle;
 73 
 74         AbstractValueLayout(Class<?> carrier, ByteOrder order, long byteSize, long byteAlignment, Optional<String> name) {
 75             super(byteSize, byteAlignment, name);
 76             this.carrier = carrier;
 77             this.order = order;
 78             assertCarrierSize(carrier, byteSize);
 79         }
 80 
 81         /**
 82          * {@return the value's byte order}
 83          */
 84         public final ByteOrder order() {
 85             return order;
 86         }
 87 
 88         /**
 89          * Returns a value layout with the same carrier, alignment constraints and name as this value layout,
 90          * but with the specified byte order.
 91          *
 92          * @param order the desired byte order.
 93          * @return a value layout with the given byte order.
 94          */
 95         public final V withOrder(ByteOrder order) {
 96             Objects.requireNonNull(order);
 97             return dup(order, byteAlignment(), name());
 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) {
156             assert isValidCarrier(carrier);
157             assert carrier != MemorySegment.class
158                     // MemorySegment byteSize must always equal ADDRESS_SIZE_BYTES
159                     || byteSize == ADDRESS_SIZE_BYTES;
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
201         OfBooleanImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
202             return new OfBooleanImpl(order, byteAlignment, name);
203         }
204 
205         public static OfBoolean of(ByteOrder order) {
206             return new OfBooleanImpl(order, Byte.BYTES, Optional.empty());
207         }
208     }
209 
210     public static final class OfByteImpl extends AbstractValueLayout<OfByteImpl> implements ValueLayout.OfByte {
211 
212         private OfByteImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
213             super(byte.class, order, Byte.BYTES, byteAlignment, name);
214         }
215 
216         @Override
217         OfByteImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
218             return new OfByteImpl(order, byteAlignment, name);
219         }
220 
221         public static OfByte of(ByteOrder order) {
222             return new OfByteImpl(order, Byte.BYTES, Optional.empty());
223         }
224     }
225 
226     public static final class OfCharImpl extends AbstractValueLayout<OfCharImpl> implements ValueLayout.OfChar {
227 
228         private OfCharImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
229             super(char.class, order, Character.BYTES, byteAlignment, name);
230         }
231 
232         @Override
233         OfCharImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
234             return new OfCharImpl(order, byteAlignment, name);
235         }
236 
237         public static OfChar of(ByteOrder order) {
238             return new OfCharImpl(order, Character.BYTES, Optional.empty());
239         }
240     }
241 
242     public static final class OfShortImpl extends AbstractValueLayout<OfShortImpl> implements ValueLayout.OfShort {
243 
244         private OfShortImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
245             super(short.class, order, Short.BYTES, byteAlignment, name);
246         }
247 
248         @Override
249         OfShortImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
250             return new OfShortImpl(order, byteAlignment, name);
251         }
252 
253         public static OfShort of(ByteOrder order) {
254             return new OfShortImpl(order, Short.BYTES, Optional.empty());
255         }
256     }
257 
258     public static final class OfIntImpl extends AbstractValueLayout<OfIntImpl> implements ValueLayout.OfInt {
259 
260         private OfIntImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
261             super(int.class, order, Integer.BYTES, byteAlignment, name);
262         }
263 
264         @Override
265         OfIntImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
266             return new OfIntImpl(order, byteAlignment, name);
267         }
268 
269         public static OfInt of(ByteOrder order) {
270             return new OfIntImpl(order, Integer.BYTES, Optional.empty());
271         }
272     }
273 
274     public static final class OfFloatImpl extends AbstractValueLayout<OfFloatImpl> implements ValueLayout.OfFloat {
275 
276         private OfFloatImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
277             super(float.class, order, Float.BYTES, byteAlignment, name);
278         }
279 
280         @Override
281         OfFloatImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
282             return new OfFloatImpl(order, byteAlignment, name);
283         }
284 
285         public static OfFloat of(ByteOrder order) {
286             return new OfFloatImpl(order, Float.BYTES, Optional.empty());
287         }
288     }
289 
290     public static final class OfLongImpl extends AbstractValueLayout<OfLongImpl> implements ValueLayout.OfLong {
291 
292         private OfLongImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
293             super(long.class, order, Long.BYTES, byteAlignment, name);
294         }
295 
296         @Override
297         OfLongImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
298             return new OfLongImpl(order, byteAlignment, name);
299         }
300 
301         public static OfLong of(ByteOrder order) {
302             return new OfLongImpl(order, ADDRESS_SIZE_BYTES, Optional.empty());
303         }
304     }
305 
306     public static final class OfDoubleImpl extends AbstractValueLayout<OfDoubleImpl> implements ValueLayout.OfDouble {
307 
308         private OfDoubleImpl(ByteOrder order, long byteAlignment, Optional<String> name) {
309             super(double.class, order, Double.BYTES, byteAlignment, name);
310         }
311 
312         @Override
313         OfDoubleImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
314             return new OfDoubleImpl(order, byteAlignment, name);
315         }
316 
317         public static OfDouble of(ByteOrder order) {
318             return new OfDoubleImpl(order, ADDRESS_SIZE_BYTES, Optional.empty());
319         }
320 
321     }
322 
323     public static final class OfAddressImpl extends AbstractValueLayout<OfAddressImpl> implements AddressLayout {
324 
325         private final MemoryLayout targetLayout;
326 
327         private OfAddressImpl(ByteOrder order, long byteSize, long byteAlignment, MemoryLayout targetLayout, Optional<String> name) {
328             super(MemorySegment.class, order, byteSize, byteAlignment, name);
329             this.targetLayout = targetLayout;
330         }
331 
332         @Override
333         OfAddressImpl dup(ByteOrder order, long byteAlignment, Optional<String> name) {
334             return new OfAddressImpl(order, byteSize(), byteAlignment,targetLayout, name);
335         }
336 
337         @Override
338         public boolean equals(Object other) {
339             return super.equals(other) &&
340                     Objects.equals(((OfAddressImpl)other).targetLayout, this.targetLayout);
341         }
342 
343         @Override
344         public int hashCode() {
345             return Objects.hash(super.hashCode(), targetLayout);
346         }
347 
348         @Override
349         @CallerSensitive
350         public AddressLayout withTargetLayout(MemoryLayout layout) {
351             Reflection.ensureNativeAccess(Reflection.getCallerClass(), AddressLayout.class, "withTargetLayout");
352             Objects.requireNonNull(layout);
353             return new OfAddressImpl(order(), byteSize(), byteAlignment(), layout, name());
354         }
355 
356         @Override
357         public AddressLayout withoutTargetLayout() {
358             return new OfAddressImpl(order(), byteSize(), byteAlignment(), null, name());
359         }
360 
361         @Override
362         public Optional<MemoryLayout> targetLayout() {
363             return Optional.ofNullable(targetLayout);
364         }
365 
366         public static AddressLayout of(ByteOrder order) {
367             return new OfAddressImpl(order, ADDRESS_SIZE_BYTES, ADDRESS_SIZE_BYTES, null, Optional.empty());
368         }
369 
370         @Override
371         public String toString() {
372             char descriptor = 'A';
373             if (order() == ByteOrder.LITTLE_ENDIAN) {
374                 descriptor = Character.toLowerCase(descriptor);
375             }
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) {
417             return ValueLayouts.OfFloatImpl.of(order);
418         } else if (carrier == long.class) {
419             return ValueLayouts.OfLongImpl.of(order);
420         } else if (carrier == double.class) {
421             return ValueLayouts.OfDoubleImpl.of(order);
422         } else if (carrier == MemorySegment.class) {
423             return ValueLayouts.OfAddressImpl.of(order);
424         } else {
425             throw new IllegalArgumentException("Unsupported carrier: " + carrier.getName());
426         }
427     }
428 }