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 }