1 /*
  2  *  Copyright (c) 2019, 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.incubator.foreign;
 27 
 28 import jdk.internal.foreign.Utils;
 29 import jdk.internal.misc.Unsafe;
 30 import jdk.internal.vm.annotation.ForceInline;
 31 import jdk.internal.vm.annotation.Stable;
 32 import sun.invoke.util.Wrapper;
 33 
 34 import java.lang.constant.ConstantDescs;
 35 import java.lang.constant.DynamicConstantDesc;
 36 import java.lang.invoke.VarHandle;
 37 import java.nio.ByteOrder;
 38 import java.util.Objects;
 39 import java.util.Optional;
 40 import java.util.OptionalLong;
 41 
 42 /**
 43  * 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
 44  * (either signed or unsigned) and <em>floating-point</em> types. Each value layout has a size, a {@linkplain ByteOrder byte order})
 45  * and a <em>carrier</em>, that is, the Java type that should be used when {@linkplain MemorySegment#get(OfInt, long) accessing}
 46  * a memory region using the value layout.
 47  * <p>
 48  * This class defines useful value layout constants for Java primitive types and addresses.
 49  * The layout constants in this class make implicit alignment and byte-ordering assumption: all layout
 50  * constants in this class are byte-aligned, and their byte order is set to the {@linkplain ByteOrder#nativeOrder() platform default},
 51  * thus making it easy to work with other APIs, such as arrays and {@link java.nio.ByteBuffer}.
 52  * <p>
 53  * This is a <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>
 54  * class; programmers should treat instances that are
 55  * {@linkplain #equals(Object) equal} as interchangeable and should not
 56  * use instances for synchronization, or unpredictable behavior may
 57  * occur. For example, in a future release, synchronization may fail.
 58  * The {@code equals} method should be used for comparisons.
 59  *
 60  * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
 61  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
 62  *
 63  * @implSpec
 64  * This class is immutable and thread-safe.
 65  */
 66 public sealed class ValueLayout extends AbstractLayout implements MemoryLayout {
 67 
 68     private final Class<?> carrier;
 69     private final ByteOrder order;
 70 
 71     ValueLayout(Class<?> carrier, ByteOrder order, long size) {
 72         this(carrier, order, size, size, Optional.empty());
 73     }
 74 
 75     ValueLayout(Class<?> carrier, ByteOrder order, long size, long alignment, Optional<String> name) {
 76         super(OptionalLong.of(size), alignment, name);
 77         this.carrier = carrier;
 78         this.order = order;
 79         checkCarrierSize(carrier, size);
 80     }
 81 
 82     /**
 83      * Returns the value's byte order.
 84      *
 85      * @return the value's  byte order.
 86      */
 87     public ByteOrder order() {
 88         return order;
 89     }
 90 
 91     /**
 92      * Returns a new value layout with given byte order.
 93      *
 94      * @param order the desired byte order.
 95      * @return a new value layout with given byte order.
 96      */
 97     public ValueLayout withOrder(ByteOrder order) {
 98         return new ValueLayout(carrier, Objects.requireNonNull(order), bitSize(), alignment, name());
 99     }
100 
101     @Override
102     public String toString() {
103         return decorateLayoutString(String.format("%s%d",
104                 order == ByteOrder.BIG_ENDIAN ? "B" : "b",
105                 bitSize()));
106     }
107 
108     @Override
109     public boolean equals(Object other) {
110         if (this == other) {
111             return true;
112         }
113         if (!super.equals(other)) {
114             return false;
115         }
116         if (!(other instanceof ValueLayout v)) {
117             return false;
118         }
119         return carrier.equals(v.carrier) &&
120             order.equals(v.order) &&
121             bitSize() == v.bitSize() &&
122             alignment == v.alignment;
123     }
124 
125     /**
126      * Returns the carrier associated with this value layout.
127      * @return the carrier associated with this value layout.
128      */
129     public Class<?> carrier() {
130         return carrier;
131     }
132 
133     @Override
134     public int hashCode() {
135         return Objects.hash(super.hashCode(), order, bitSize(), alignment);
136     }
137 
138     @Override
139     ValueLayout dup(long alignment, Optional<String> name) {
140         return new ValueLayout(carrier, order, bitSize(), alignment, name());
141     }
142 
143     @Override
144     public Optional<DynamicConstantDesc<ValueLayout>> describeConstable() {
145         return Optional.of(decorateLayoutConstant(DynamicConstantDesc.ofNamed(ConstantDescs.BSM_INVOKE, "value",
146                 CD_VALUE_LAYOUT, MH_VALUE, carrier().describeConstable().get(), order == ByteOrder.BIG_ENDIAN ? BIG_ENDIAN : LITTLE_ENDIAN)));
147     }
148 
149     //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout
150     //but that causes issues with javadoc, see JDK-8224052
151 
152     /**
153      * {@inheritDoc}
154      */
155     @Override
156     public ValueLayout withName(String name) {
157         return (ValueLayout)super.withName(name);
158     }
159 
160     /**
161      * {@inheritDoc}
162      */
163     @Override
164     public ValueLayout withBitAlignment(long alignmentBits) {
165         return (ValueLayout)super.withBitAlignment(alignmentBits);
166     }
167 
168     static void checkCarrierSize(Class<?> carrier, long size) {
169         if (!isValidCarrier(carrier)) {
170             throw new IllegalArgumentException("Invalid carrier: " + carrier.getName());
171         }
172         if (carrier == void.class) return;
173         if (carrier == MemoryAddress.class && size != (Unsafe.ADDRESS_SIZE * 8)) {
174             throw new IllegalArgumentException("Address size mismatch: " + (Unsafe.ADDRESS_SIZE * 8) + " != " + size);
175         }
176         if (carrier.isPrimitive() && Wrapper.forPrimitiveType(carrier).bitWidth() != size &&
177                 carrier != boolean.class && size != 8) {
178             throw new IllegalArgumentException("Carrier size mismatch: " + carrier.getName() + " != " + size);
179         }
180     }
181 
182     static boolean isValidCarrier(Class<?> carrier) {
183         return carrier == void.class
184                 || carrier == boolean.class
185                 || carrier == byte.class
186                 || carrier == short.class
187                 || carrier == char.class
188                 || carrier == int.class
189                 || carrier == long.class
190                 || carrier == float.class
191                 || carrier == double.class
192                 || carrier == MemoryAddress.class;
193     }
194 
195     @Stable
196     private VarHandle handle;
197 
198     @ForceInline
199     VarHandle accessHandle() {
200         if (handle == null) {
201             handle = Utils.makeMemoryAccessVarHandle(carrier, false, byteAlignment() - 1, order());
202         }
203         return handle;
204     }
205 
206     /**
207      * A value layout whose carrier is {@code boolean.class}.
208      */
209     public static final class OfBoolean extends ValueLayout {
210         OfBoolean(ByteOrder order) {
211             super(boolean.class, order, 8);
212         }
213 
214         OfBoolean(ByteOrder order, long alignment, Optional<String> name) {
215             super(boolean.class, order, 8, alignment, name);
216         }
217 
218         @Override
219         OfBoolean dup(long alignment, Optional<String> name) {
220             return new OfBoolean(order(), alignment, name);
221         }
222 
223         @Override
224         public OfBoolean withName(String name) {
225             return (OfBoolean)super.withName(name);
226         }
227 
228         @Override
229         public OfBoolean withBitAlignment(long alignmentBits) {
230             return (OfBoolean)super.withBitAlignment(alignmentBits);
231         }
232 
233         @Override
234         public OfBoolean withOrder(ByteOrder order) {
235             Objects.requireNonNull(order);
236             return new OfBoolean(order, alignment, name());
237         }
238     }
239 
240     /**
241      * A value layout whose carrier is {@code byte.class}.
242      */
243     public static final class OfByte extends ValueLayout {
244         OfByte(ByteOrder order) {
245             super(byte.class, order, 8);
246         }
247 
248         OfByte(ByteOrder order, long alignment, Optional<String> name) {
249             super(byte.class, order, 8, alignment, name);
250         }
251 
252         @Override
253         OfByte dup(long alignment, Optional<String> name) {
254             return new OfByte(order(), alignment, name);
255         }
256 
257         @Override
258         public OfByte withName(String name) {
259             return (OfByte)super.withName(name);
260         }
261 
262         @Override
263         public OfByte withBitAlignment(long alignmentBits) {
264             return (OfByte)super.withBitAlignment(alignmentBits);
265         }
266 
267         @Override
268         public OfByte withOrder(ByteOrder order) {
269             Objects.requireNonNull(order);
270             return new OfByte(order, alignment, name());
271         }
272     }
273 
274     /**
275      * A value layout whose carrier is {@code char.class}.
276      */
277     public static final class OfChar extends ValueLayout {
278         OfChar(ByteOrder order) {
279             super(char.class, order, 16);
280         }
281 
282         OfChar(ByteOrder order, long alignment, Optional<String> name) {
283             super(char.class, order, 16, alignment, name);
284         }
285 
286         @Override
287         OfChar dup(long alignment, Optional<String> name) {
288             return new OfChar(order(), alignment, name);
289         }
290 
291         @Override
292         public OfChar withName(String name) {
293             return (OfChar)super.withName(name);
294         }
295 
296         @Override
297         public OfChar withBitAlignment(long alignmentBits) {
298             return (OfChar)super.withBitAlignment(alignmentBits);
299         }
300 
301         @Override
302         public OfChar withOrder(ByteOrder order) {
303             Objects.requireNonNull(order);
304             return new OfChar(order, alignment, name());
305         }
306     }
307 
308     /**
309      * A value layout whose carrier is {@code short.class}.
310      */
311     public static final class OfShort extends ValueLayout {
312         OfShort(ByteOrder order) {
313             super(short.class, order, 16);
314         }
315 
316         OfShort(ByteOrder order, long alignment, Optional<String> name) {
317             super(short.class, order, 16, alignment, name);
318         }
319 
320         @Override
321         OfShort dup(long alignment, Optional<String> name) {
322             return new OfShort(order(), alignment, name);
323         }
324 
325         @Override
326         public OfShort withName(String name) {
327             return (OfShort)super.withName(name);
328         }
329 
330         @Override
331         public OfShort withBitAlignment(long alignmentBits) {
332             return (OfShort)super.withBitAlignment(alignmentBits);
333         }
334 
335         @Override
336         public OfShort withOrder(ByteOrder order) {
337             Objects.requireNonNull(order);
338             return new OfShort(order, alignment, name());
339         }
340     }
341 
342     /**
343      * A value layout whose carrier is {@code int.class}.
344      */
345     public static final class OfInt extends ValueLayout {
346         OfInt(ByteOrder order) {
347             super(int.class, order, 32);
348         }
349 
350         OfInt(ByteOrder order, long alignment, Optional<String> name) {
351             super(int.class, order, 32, alignment, name);
352         }
353 
354         @Override
355         OfInt dup(long alignment, Optional<String> name) {
356             return new OfInt(order(), alignment, name);
357         }
358 
359         @Override
360         public OfInt withName(String name) {
361             return (OfInt)super.withName(name);
362         }
363 
364         @Override
365         public OfInt withBitAlignment(long alignmentBits) {
366             return (OfInt)super.withBitAlignment(alignmentBits);
367         }
368 
369         @Override
370         public OfInt withOrder(ByteOrder order) {
371             Objects.requireNonNull(order);
372             return new OfInt(order, alignment, name());
373         }
374     }
375 
376     /**
377      * A value layout whose carrier is {@code float.class}.
378      */
379     public static final class OfFloat extends ValueLayout {
380         OfFloat(ByteOrder order) {
381             super(float.class, order, 32);
382         }
383 
384         OfFloat(ByteOrder order, long alignment, Optional<String> name) {
385             super(float.class, order, 32, alignment, name);
386         }
387 
388         @Override
389         OfFloat dup(long alignment, Optional<String> name) {
390             return new OfFloat(order(), alignment, name);
391         }
392 
393         @Override
394         public OfFloat withName(String name) {
395             return (OfFloat)super.withName(name);
396         }
397 
398         @Override
399         public OfFloat withBitAlignment(long alignmentBits) {
400             return (OfFloat)super.withBitAlignment(alignmentBits);
401         }
402 
403         @Override
404         public OfFloat withOrder(ByteOrder order) {
405             Objects.requireNonNull(order);
406             return new OfFloat(order, alignment, name());
407         }
408     }
409 
410     /**
411      * A value layout whose carrier is {@code long.class}.
412      */
413     public static final class OfLong extends ValueLayout {
414         OfLong(ByteOrder order) {
415             super(long.class, order, 64);
416         }
417 
418         OfLong(ByteOrder order, long alignment, Optional<String> name) {
419             super(long.class, order, 64, alignment, name);
420         }
421 
422         @Override
423         OfLong dup(long alignment, Optional<String> name) {
424             return new OfLong(order(), alignment, name);
425         }
426 
427         @Override
428         public OfLong withName(String name) {
429             return (OfLong)super.withName(name);
430         }
431 
432         @Override
433         public OfLong withBitAlignment(long alignmentBits) {
434             return (OfLong)super.withBitAlignment(alignmentBits);
435         }
436 
437         @Override
438         public OfLong withOrder(ByteOrder order) {
439             Objects.requireNonNull(order);
440             return new OfLong(order, alignment, name());
441         }
442     }
443 
444     /**
445      * A value layout whose carrier is {@code double.class}.
446      */
447     public static final class OfDouble extends ValueLayout {
448         OfDouble(ByteOrder order) {
449             super(double.class, order, 64);
450         }
451 
452         OfDouble(ByteOrder order, long alignment, Optional<String> name) {
453             super(double.class, order, 64, alignment, name);
454         }
455 
456         @Override
457         OfDouble dup(long alignment, Optional<String> name) {
458             return new OfDouble(order(), alignment, name);
459         }
460 
461         @Override
462         public OfDouble withName(String name) {
463             return (OfDouble)super.withName(name);
464         }
465 
466         @Override
467         public OfDouble withBitAlignment(long alignmentBits) {
468             return (OfDouble)super.withBitAlignment(alignmentBits);
469         }
470 
471         @Override
472         public OfDouble withOrder(ByteOrder order) {
473             Objects.requireNonNull(order);
474             return new OfDouble(order, alignment, name());
475         }
476     }
477 
478     /**
479      * A value layout whose carrier is {@code MemoryAddress.class}.
480      */
481     public static final class OfAddress extends ValueLayout {
482         OfAddress(ByteOrder order) {
483             super(MemoryAddress.class, order, Unsafe.ADDRESS_SIZE * 8);
484         }
485 
486         OfAddress(ByteOrder order, long size, long alignment, Optional<String> name) {
487             super(MemoryAddress.class, order, size, alignment, name);
488         }
489 
490         @Override
491         OfAddress dup(long alignment, Optional<String> name) {
492             return new OfAddress(order(), bitSize(), alignment, name);
493         }
494 
495         @Override
496         public OfAddress withName(String name) {
497             return (OfAddress)super.withName(name);
498         }
499 
500         @Override
501         public OfAddress withBitAlignment(long alignmentBits) {
502             return (OfAddress)super.withBitAlignment(alignmentBits);
503         }
504 
505         @Override
506         public OfAddress withOrder(ByteOrder order) {
507             Objects.requireNonNull(order);
508             return new OfAddress(order, bitSize(), alignment, name());
509         }
510     }
511 
512     /**
513      * A value layout constant whose size is the same as that of a machine address (e.g. {@code size_t}),
514      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
515      * Equivalent to the following code:
516      * <blockquote><pre>{@code
517     MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()).withBitAlignment(8);
518      * }</pre></blockquote>
519      */
520     public static final OfAddress ADDRESS = new OfAddress(ByteOrder.nativeOrder()).withBitAlignment(8);
521 
522     /**
523      * A value layout constant whose size is the same as that of a Java {@code byte},
524      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
525      * Equivalent to the following code:
526      * <blockquote><pre>{@code
527     MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8);
528      * }</pre></blockquote>
529      */
530     public static final OfByte JAVA_BYTE = new OfByte(ByteOrder.nativeOrder()).withBitAlignment(8);
531 
532     /**
533      * A value layout constant whose size is the same as that of a Java {@code boolean},
534      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
535      * Equivalent to the following code:
536      * <blockquote><pre>{@code
537     MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8);
538      * }</pre></blockquote>
539      */
540     public static final OfBoolean JAVA_BOOLEAN = new OfBoolean(ByteOrder.nativeOrder()).withBitAlignment(8);
541 
542     /**
543      * A value layout constant whose size is the same as that of a Java {@code char},
544      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
545      * Equivalent to the following code:
546      * <blockquote><pre>{@code
547     MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(8);
548      * }</pre></blockquote>
549      */
550     public static final OfChar JAVA_CHAR = new OfChar(ByteOrder.nativeOrder()).withBitAlignment(8);
551 
552     /**
553      * A value layout constant whose size is the same as that of a Java {@code short},
554      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
555      * Equivalent to the following code:
556      * <blockquote><pre>{@code
557     MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(8);
558      * }</pre></blockquote>
559      */
560     public static final OfShort JAVA_SHORT = new OfShort(ByteOrder.nativeOrder()).withBitAlignment(8);
561 
562     /**
563      * A value layout constant whose size is the same as that of a Java {@code int},
564      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
565      * Equivalent to the following code:
566      * <blockquote><pre>{@code
567     MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(8);
568      * }</pre></blockquote>
569      */
570     public static final OfInt JAVA_INT = new OfInt(ByteOrder.nativeOrder()).withBitAlignment(8);
571 
572     /**
573      * A value layout constant whose size is the same as that of a Java {@code long},
574      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
575      * Equivalent to the following code:
576      * <blockquote><pre>{@code
577     MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(8);
578      * }</pre></blockquote>
579      */
580     public static final OfLong JAVA_LONG = new OfLong(ByteOrder.nativeOrder())
581             .withBitAlignment(8);
582 
583     /**
584      * A value layout constant whose size is the same as that of a Java {@code float},
585      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
586      * Equivalent to the following code:
587      * <blockquote><pre>{@code
588     MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(8);
589      * }</pre></blockquote>
590      */
591     public static final OfFloat JAVA_FLOAT = new OfFloat(ByteOrder.nativeOrder()).withBitAlignment(8);
592 
593     /**
594      * A value layout constant whose size is the same as that of a Java {@code double},
595      * bit-alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}.
596      * Equivalent to the following code:
597      * <blockquote><pre>{@code
598     MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(8);
599      * }</pre></blockquote>
600      */
601     public static final OfDouble JAVA_DOUBLE = new OfDouble(ByteOrder.nativeOrder()).withBitAlignment(8);
602 }