< prev index next >

src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java

Print this page

 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) {
< prev index next >