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 }