1 /*
   2  * Copyright (c) 2020, 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.access.foreign.MemorySegmentProxy;
  29 import jdk.internal.vm.annotation.ForceInline;
  30 
  31 import java.lang.invoke.VarHandle;
  32 import java.nio.ByteOrder;
  33 import java.util.Objects;
  34 
  35 /**
  36  * This class defines ready-made static accessors which can be used to dereference memory segments in many ways.
  37  * <p>
  38  * The most primitive accessors (see {@link #getIntAtOffset(MemorySegment, long, ByteOrder)}) take a segment, an offset
  39  * (expressed in bytes) and a byte order. The final address at which the dereference will occur will be computed by offsetting
  40  * the base address by the specified offset, as if by calling {@link MemoryAddress#addOffset(long)} on the specified base address.
  41  * <p>
  42  * In cases where no offset is required, overloads are provided (see {@link #getInt(MemorySegment, ByteOrder)}) so that
  43  * clients can omit the offset coordinate.
  44  * <p>
  45  * To help dereferencing in array-like use cases (e.g. where the layout of a given memory segment is a sequence
  46  * layout of given size an element count), higher-level overloads are also provided (see {@link #getIntAtIndex(MemorySegment, long, ByteOrder)}),
  47  * which take a segment and a <em>logical</em> element index. The formula to obtain the byte offset {@code O} from an
  48  * index {@code I} is given by {@code O = I * S} where {@code S} is the size (expressed in bytes) of the element to
  49  * be dereferenced.
  50  * <p>
  51  * In cases where native byte order is preferred, overloads are provided (see {@link #getIntAtOffset(MemorySegment, long)})
  52  * so that clients can omit the byte order parameter.
  53  *
  54  * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
  55  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
  56  */
  57 public final class MemoryAccess {
  58 
  59     private MemoryAccess() {
  60         // just the one
  61     }
  62 
  63     private static final VarHandle byte_handle = MemoryHandles.varHandle(byte.class, ByteOrder.nativeOrder());
  64     private static final VarHandle char_LE_handle = unalignedHandle(MemoryLayouts.BITS_16_LE, char.class);
  65     private static final VarHandle short_LE_handle = unalignedHandle(MemoryLayouts.BITS_16_LE, short.class);
  66     private static final VarHandle int_LE_handle = unalignedHandle(MemoryLayouts.BITS_32_LE, int.class);
  67     private static final VarHandle float_LE_handle = unalignedHandle(MemoryLayouts.BITS_32_LE, float.class);
  68     private static final VarHandle long_LE_handle = unalignedHandle(MemoryLayouts.BITS_64_LE, long.class);
  69     private static final VarHandle double_LE_handle = unalignedHandle(MemoryLayouts.BITS_64_LE, double.class);
  70     private static final VarHandle char_BE_handle = unalignedHandle(MemoryLayouts.BITS_16_BE, char.class);
  71     private static final VarHandle short_BE_handle = unalignedHandle(MemoryLayouts.BITS_16_BE, short.class);
  72     private static final VarHandle int_BE_handle = unalignedHandle(MemoryLayouts.BITS_32_BE, int.class);
  73     private static final VarHandle float_BE_handle = unalignedHandle(MemoryLayouts.BITS_32_BE, float.class);
  74     private static final VarHandle long_BE_handle = unalignedHandle(MemoryLayouts.BITS_64_BE, long.class);
  75     private static final VarHandle double_BE_handle = unalignedHandle(MemoryLayouts.BITS_64_BE, double.class);
  76     private static final VarHandle address_handle;
  77 
  78     static {
  79         Class<?> carrier = switch ((int) MemoryLayouts.ADDRESS.byteSize()) {
  80             case 4 -> int.class;
  81             case 8 -> long.class;
  82             default -> throw new ExceptionInInitializerError("Unsupported pointer size: " + MemoryLayouts.ADDRESS.byteSize());
  83         };
  84         address_handle = MemoryHandles.asAddressVarHandle(unalignedHandle(MemoryLayouts.ADDRESS, carrier));
  85     }
  86 
  87     private static VarHandle unalignedHandle(ValueLayout elementLayout, Class<?> carrier) {
  88         return MemoryHandles.varHandle(carrier, 1, elementLayout.order());
  89     }
  90 
  91     // Note: all the accessor methods defined below take advantage of argument type profiling
  92     // (see src/hotspot/share/oops/methodData.cpp) which greatly enhances performance when the same accessor
  93     // method is used repeatedly with different segment kinds (e.g. on-heap vs. off-heap).
  94 
  95     /**
  96      * Reads a byte from given segment and offset.
  97      *
  98      * @param segment the segment to be dereferenced.
  99      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 100      * @return a byte value read from {@code segment}.
 101      */
 102     @ForceInline
 103     public static byte getByteAtOffset(MemorySegment segment, long offset) {
 104         Objects.requireNonNull(segment);
 105         return (byte)byte_handle.get(segment, offset);
 106     }
 107 
 108     /**
 109      * Writes a byte at given segment and offset.
 110      *
 111      * @param segment the segment to be dereferenced.
 112      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 113      * @param value the byte value to be written.
 114      */
 115     @ForceInline
 116     public static void setByteAtOffset(MemorySegment segment, long offset, byte value) {
 117         Objects.requireNonNull(segment);
 118         byte_handle.set(segment, offset, value);
 119     }
 120 
 121     /**
 122      * Reads a char from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 123      * <p>
 124      * This is equivalent to the following code:
 125      * <blockquote><pre>{@code
 126     getCharAtOffset(segment, offset, ByteOrder.nativeOrder());
 127      * }</pre></blockquote>
 128      * @param segment the segment to be dereferenced.
 129      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 130      * @return a char value read from {@code segment}.
 131      */
 132     @ForceInline
 133     public static char getCharAtOffset(MemorySegment segment, long offset) {
 134         return getCharAtOffset(segment, offset, ByteOrder.nativeOrder());
 135     }
 136 
 137     /**
 138      * Writes a char at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 139      * <p>
 140      * This is equivalent to the following code:
 141      * <blockquote><pre>{@code
 142     setCharAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 143      * }</pre></blockquote>
 144      * @param segment the segment to be dereferenced.
 145      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 146      * @param value the char value to be written.
 147      */
 148     @ForceInline
 149     public static void setCharAtOffset(MemorySegment segment, long offset, char value) {
 150         setCharAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 151     }
 152 
 153     /**
 154      * Reads a short from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 155      * <p>
 156      * This is equivalent to the following code:
 157      * <blockquote><pre>{@code
 158     getShortAtOffset(segment, offset, ByteOrder.nativeOrder());
 159      * }</pre></blockquote>
 160      * @param segment the segment to be dereferenced.
 161      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 162      * @return a short value read from {@code segment}.
 163      */
 164     @ForceInline
 165     public static short getShortAtOffset(MemorySegment segment, long offset) {
 166         return getShortAtOffset(segment, offset, ByteOrder.nativeOrder());
 167     }
 168 
 169     /**
 170      * Writes a short at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 171      * <p>
 172      * This is equivalent to the following code:
 173      * <blockquote><pre>{@code
 174     setShortAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 175      * }</pre></blockquote>
 176      * @param segment the segment to be dereferenced.
 177      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 178      * @param value the short value to be written.
 179      */
 180     @ForceInline
 181     public static void setShortAtOffset(MemorySegment segment, long offset, short value) {
 182         setShortAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 183     }
 184 
 185     /**
 186      * Reads an int from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 187      * <p>
 188      * This is equivalent to the following code:
 189      * <blockquote><pre>{@code
 190     getIntAtOffset(segment, offset, ByteOrder.nativeOrder());
 191      * }</pre></blockquote>
 192      * @param segment the segment to be dereferenced.
 193      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 194      * @return an int value read from {@code segment}.
 195      */
 196     @ForceInline
 197     public static int getIntAtOffset(MemorySegment segment, long offset) {
 198         return getIntAtOffset(segment, offset, ByteOrder.nativeOrder());
 199     }
 200 
 201     /**
 202      * Writes an int at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 203      * <p>
 204      * This is equivalent to the following code:
 205      * <blockquote><pre>{@code
 206     setIntAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 207      * }</pre></blockquote>
 208      * @param segment the segment to be dereferenced.
 209      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 210      * @param value the int value to be written.
 211      */
 212     @ForceInline
 213     public static void setIntAtOffset(MemorySegment segment, long offset, int value) {
 214         setIntAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 215     }
 216 
 217     /**
 218      * Reads a float from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 219      * <p>
 220      * This is equivalent to the following code:
 221      * <blockquote><pre>{@code
 222     getFloatAtOffset(segment, offset, ByteOrder.nativeOrder());
 223      * }</pre></blockquote>
 224      * @param segment the segment to be dereferenced.
 225      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 226      * @return a float value read from {@code segment}.
 227      */
 228     @ForceInline
 229     public static float getFloatAtOffset(MemorySegment segment, long offset) {
 230         return getFloatAtOffset(segment, offset, ByteOrder.nativeOrder());
 231     }
 232 
 233     /**
 234      * Writes a float at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 235      * <p>
 236      * This is equivalent to the following code:
 237      * <blockquote><pre>{@code
 238     setFloatAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 239      * }</pre></blockquote>
 240      * @param segment the segment to be dereferenced.
 241      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 242      * @param value the float value to be written.
 243      */
 244     @ForceInline
 245     public static void setFloatAtOffset(MemorySegment segment, long offset, float value) {
 246         setFloatAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 247     }
 248 
 249     /**
 250      * Reads a long from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 251      * <p>
 252      * This is equivalent to the following code:
 253      * <blockquote><pre>{@code
 254     getLongAtOffset(segment, offset, ByteOrder.nativeOrder());
 255      * }</pre></blockquote>
 256      * @param segment the segment to be dereferenced.
 257      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 258      * @return a long value read from {@code segment}.
 259      */
 260     @ForceInline
 261     public static long getLongAtOffset(MemorySegment segment, long offset) {
 262         return getLongAtOffset(segment, offset, ByteOrder.nativeOrder());
 263     }
 264 
 265     /**
 266      * Writes a long at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 267      * <p>
 268      * This is equivalent to the following code:
 269      * <blockquote><pre>{@code
 270     setLongAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 271      * }</pre></blockquote>
 272      * @param segment the segment to be dereferenced.
 273      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 274      * @param value the long value to be written.
 275      */
 276     @ForceInline
 277     public static void setLongAtOffset(MemorySegment segment, long offset, long value) {
 278         setLongAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 279     }
 280 
 281     /**
 282      * Reads a double from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 283      * <p>
 284      * This is equivalent to the following code:
 285      * <blockquote><pre>{@code
 286     getDoubleAtOffset(segment, offset, ByteOrder.nativeOrder());
 287      * }</pre></blockquote>
 288      * @param segment the segment to be dereferenced.
 289      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 290      * @return a double value read from {@code segment}.
 291      */
 292     @ForceInline
 293     public static double getDoubleAtOffset(MemorySegment segment, long offset) {
 294         return getDoubleAtOffset(segment, offset, ByteOrder.nativeOrder());
 295     }
 296 
 297     /**
 298      * Writes a double at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 299      * <p>
 300      * This is equivalent to the following code:
 301      * <blockquote><pre>{@code
 302     setDoubleAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 303      * }</pre></blockquote>
 304      * @param segment the segment to be dereferenced.
 305      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 306      * @param value the double value to be written.
 307      */
 308     @ForceInline
 309     public static void setDoubleAtOffset(MemorySegment segment, long offset, double value) {
 310         setDoubleAtOffset(segment, offset, ByteOrder.nativeOrder(), value);
 311     }
 312 
 313     /**
 314      * Reads a memory address from given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 315      * <p>
 316      * This is equivalent (e.g. on a 64-bit platform) to the following code:
 317      * <blockquote><pre>{@code
 318     VarHandle handle = MemoryHandles.asAddressHandle(MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder()));
 319     MemoryAddress value = (MemoryAddress)handle.get(segment, offset);
 320      * }</pre></blockquote>
 321      * @param segment the segment to be dereferenced.
 322      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 323      * @return a memory address read from {@code segment}.
 324      */
 325     @ForceInline
 326     public static MemoryAddress getAddressAtOffset(MemorySegment segment, long offset) {
 327         Objects.requireNonNull(segment);
 328         return (MemoryAddress)address_handle.get(segment, offset);
 329     }
 330 
 331     /**
 332      * Writes a memory address at given segment and offset, with byte order set to {@link ByteOrder#nativeOrder()}.
 333      * <p>
 334      * This is equivalent (e.g. on a 64-bit platform) to the following code:
 335      * <blockquote><pre>{@code
 336     VarHandle handle = MemoryHandles.asAddressHandle(MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder()));
 337     handle.set(segment, offset, value.address());
 338      * }</pre></blockquote>
 339      * @param segment the segment to be dereferenced.
 340      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 341      * @param value the memory address to be written (expressed as an {@link Addressable} instance).
 342      */
 343     @ForceInline
 344     public static void setAddressAtOffset(MemorySegment segment, long offset, Addressable value) {
 345         Objects.requireNonNull(segment);
 346         Objects.requireNonNull(value);
 347         address_handle.set(segment, offset, value.address());
 348     }
 349 
 350     /**
 351      * Reads a char from given segment and offset with given byte order.
 352      * <p>
 353      * This is equivalent to the following code:
 354      * <blockquote><pre>{@code
 355     VarHandle handle = MemoryHandles.varHandle(char.class, 1, order);
 356     char value = (char)handle.get(segment, offset);
 357      * }</pre></blockquote>
 358      * @param segment the segment to be dereferenced.
 359      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 360      * @param order the specified byte order.
 361      * @return a char value read from {@code segment}.
 362      */
 363     @ForceInline
 364     public static char getCharAtOffset(MemorySegment segment, long offset, ByteOrder order) {
 365         Objects.requireNonNull(segment);
 366         Objects.requireNonNull(order);
 367         return (char)((order == ByteOrder.BIG_ENDIAN) ? char_BE_handle : char_LE_handle).get(segment, offset);
 368     }
 369 
 370     /**
 371      * Writes a char at given segment and offset with given byte order.
 372      * <p>
 373      * This is equivalent to the following code:
 374      * <blockquote><pre>{@code
 375     VarHandle handle = MemoryHandles.varHandle(char.class, 1, order);
 376     handle.set(segment, offset, value);
 377      * }</pre></blockquote>
 378      * @param segment the segment to be dereferenced.
 379      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 380      * @param order the specified byte order.
 381      * @param value the char value to be written.
 382      */
 383     @ForceInline
 384     public static void setCharAtOffset(MemorySegment segment, long offset, ByteOrder order, char value) {
 385         Objects.requireNonNull(segment);
 386         Objects.requireNonNull(order);
 387         ((order == ByteOrder.BIG_ENDIAN) ? char_BE_handle : char_LE_handle).set(segment, offset, value);
 388     }
 389 
 390     /**
 391      * Reads a short from given segment and offset with given byte order.
 392      * <p>
 393      * This is equivalent to the following code:
 394      * <blockquote><pre>{@code
 395     VarHandle handle = MemoryHandles.varHandle(short.class, 1, order);
 396     short value = (short)handle.get(segment, offset);
 397      * }</pre></blockquote>
 398      * @param segment the segment to be dereferenced.
 399      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 400      * @param order the specified byte order.
 401      * @return a short value read from {@code segment}.
 402      */
 403     @ForceInline
 404     public static short getShortAtOffset(MemorySegment segment, long offset, ByteOrder order) {
 405         Objects.requireNonNull(segment);
 406         Objects.requireNonNull(order);
 407         return (short)((order == ByteOrder.BIG_ENDIAN) ? short_BE_handle : short_LE_handle).get(segment, offset);
 408     }
 409 
 410     /**
 411      * Writes a short at given segment and offset with given byte order.
 412      * <p>
 413      * This is equivalent to the following code:
 414      * <blockquote><pre>{@code
 415     VarHandle handle = MemoryHandles.varHandle(short.class, 1, order);
 416     handle.set(segment, offset, value);
 417      * }</pre></blockquote>
 418      * @param segment the segment to be dereferenced.
 419      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 420      * @param order the specified byte order.
 421      * @param value the short value to be written.
 422      */
 423     @ForceInline
 424     public static void setShortAtOffset(MemorySegment segment, long offset, ByteOrder order, short value) {
 425         Objects.requireNonNull(segment);
 426         Objects.requireNonNull(order);
 427         ((order == ByteOrder.BIG_ENDIAN) ? short_BE_handle : short_LE_handle).set(segment, offset, value);
 428     }
 429 
 430     /**
 431      * Reads an int from given segment and offset with given byte order.
 432      * <p>
 433      * This is equivalent to the following code:
 434      * <blockquote><pre>{@code
 435     VarHandle handle = MemoryHandles.varHandle(int.class, 1, order);
 436     int value = (int)handle.get(segment, offset);
 437      * }</pre></blockquote>
 438      * @param segment the segment to be dereferenced.
 439      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 440      * @param order the specified byte order.
 441      * @return an int value read from {@code segment}.
 442      */
 443     @ForceInline
 444     public static int getIntAtOffset(MemorySegment segment, long offset, ByteOrder order) {
 445         Objects.requireNonNull(segment);
 446         Objects.requireNonNull(order);
 447         return (int)((order == ByteOrder.BIG_ENDIAN) ? int_BE_handle : int_LE_handle).get(segment, offset);
 448     }
 449 
 450     /**
 451      * Writes an int at given segment and offset with given byte order.
 452      * <p>
 453      * This is equivalent to the following code:
 454      * <blockquote><pre>{@code
 455     VarHandle handle = MemoryHandles.varHandle(int.class, 1, order);
 456     handle.set(segment, offset, value);
 457      * }</pre></blockquote>
 458      * @param segment the segment to be dereferenced.
 459      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 460      * @param order the specified byte order.
 461      * @param value the int value to be written.
 462      */
 463     @ForceInline
 464     public static void setIntAtOffset(MemorySegment segment, long offset, ByteOrder order, int value) {
 465         Objects.requireNonNull(segment);
 466         Objects.requireNonNull(order);
 467         ((order == ByteOrder.BIG_ENDIAN) ? int_BE_handle : int_LE_handle).set(segment, offset, value);
 468     }
 469 
 470     /**
 471      * Reads a float from given segment and offset with given byte order.
 472      * <p>
 473      * This is equivalent to the following code:
 474      * <blockquote><pre>{@code
 475     VarHandle handle = MemoryHandles.varHandle(float.class, 1, order);
 476     float value = (float)handle.get(segment, offset);
 477      * }</pre></blockquote>
 478      * @param segment the segment to be dereferenced.
 479      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 480      * @param order the specified byte order.
 481      * @return a float value read from {@code segment}.
 482      */
 483     @ForceInline
 484     public static float getFloatAtOffset(MemorySegment segment, long offset, ByteOrder order) {
 485         Objects.requireNonNull(segment);
 486         Objects.requireNonNull(order);
 487         return (float)((order == ByteOrder.BIG_ENDIAN) ? float_BE_handle : float_LE_handle).get(segment, offset);
 488     }
 489 
 490     /**
 491      * Writes a float at given segment and offset with given byte order.
 492      * <p>
 493      * This is equivalent to the following code:
 494      * <blockquote><pre>{@code
 495     VarHandle handle = MemoryHandles.varHandle(float.class, 1, order);
 496     handle.set(segment, offset, value);
 497      * }</pre></blockquote>
 498      * @param segment the segment to be dereferenced.
 499      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 500      * @param order the specified byte order.
 501      * @param value the float value to be written.
 502      */
 503     @ForceInline
 504     public static void setFloatAtOffset(MemorySegment segment, long offset, ByteOrder order, float value) {
 505         Objects.requireNonNull(segment);
 506         Objects.requireNonNull(order);
 507         ((order == ByteOrder.BIG_ENDIAN) ? float_BE_handle : float_LE_handle).set(segment, offset, value);
 508     }
 509 
 510     /**
 511      * Reads a long from given segment and offset with given byte order.
 512      * <p>
 513      * This is equivalent to the following code:
 514      * <blockquote><pre>{@code
 515     VarHandle handle = MemoryHandles.varHandle(long.class, 1, order);
 516     long value = (long)handle.get(segment, offset);
 517      * }</pre></blockquote>
 518      * @param segment the segment to be dereferenced.
 519      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 520      * @param order the specified byte order.
 521      * @return a long value read from {@code segment}.
 522      */
 523     @ForceInline
 524     public static long getLongAtOffset(MemorySegment segment, long offset, ByteOrder order) {
 525         Objects.requireNonNull(segment);
 526         Objects.requireNonNull(order);
 527         return (long)((order == ByteOrder.BIG_ENDIAN) ? long_BE_handle : long_LE_handle).get(segment, offset);
 528     }
 529 
 530     /**
 531      * Writes a long at given segment and offset with given byte order.
 532      * <p>
 533      * This is equivalent to the following code:
 534      * <blockquote><pre>{@code
 535     VarHandle handle = MemoryHandles.varHandle(long.class, 1, order);
 536     handle.set(segment, offset, value);
 537      * }</pre></blockquote>
 538      * @param segment the segment to be dereferenced.
 539      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 540      * @param order the specified byte order.
 541      * @param value the long value to be written.
 542      */
 543     @ForceInline
 544     public static void setLongAtOffset(MemorySegment segment, long offset, ByteOrder order, long value) {
 545         Objects.requireNonNull(segment);
 546         Objects.requireNonNull(order);
 547         ((order == ByteOrder.BIG_ENDIAN) ? long_BE_handle : long_LE_handle).set(segment, offset, value);
 548     }
 549 
 550     /**
 551      * Reads a double from given segment and offset with given byte order.
 552      * <p>
 553      * This is equivalent to the following code:
 554      * <blockquote><pre>{@code
 555     VarHandle handle = MemoryHandles.varHandle(double.class, 1, order);
 556     double value = (double)handle.get(segment, offset);
 557      * }</pre></blockquote>
 558      * @param segment the segment to be dereferenced.
 559      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 560      * @param order the specified byte order.
 561      * @return a double value read from {@code segment}.
 562      */
 563     @ForceInline
 564     public static double getDoubleAtOffset(MemorySegment segment, long offset, ByteOrder order) {
 565         Objects.requireNonNull(segment);
 566         Objects.requireNonNull(order);
 567         return (double)((order == ByteOrder.BIG_ENDIAN) ? double_BE_handle : double_LE_handle).get(segment, offset);
 568     }
 569 
 570     /**
 571      * Writes a double at given segment and offset with given byte order.
 572      * <p>
 573      * This is equivalent to the following code:
 574      * <blockquote><pre>{@code
 575     VarHandle handle = MemoryHandles.varHandle(double.class, 1, order);
 576     handle.set(segment, offset, value);
 577      * }</pre></blockquote>
 578      * @param segment the segment to be dereferenced.
 579      * @param offset offset in bytes (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(offset)}.
 580      * @param order the specified byte order.
 581      * @param value the double value to be written.
 582      */
 583     @ForceInline
 584     public static void setDoubleAtOffset(MemorySegment segment, long offset, ByteOrder order, double value) {
 585         Objects.requireNonNull(segment);
 586         Objects.requireNonNull(order);
 587         ((order == ByteOrder.BIG_ENDIAN) ? double_BE_handle : double_LE_handle).set(segment, offset, value);
 588     }
 589 
 590     /**
 591      * Reads a byte from given segment.
 592      * <p>
 593      * This is equivalent to the following code:
 594      * <blockquote><pre>{@code
 595     byte value = getByteAtOffset(segment, 0L);
 596      * }</pre></blockquote>
 597      *
 598      * @param segment the segment to be dereferenced.
 599      * @return a byte value read from {@code segment}.
 600      */
 601     @ForceInline
 602     public static byte getByte(MemorySegment segment) {
 603         return getByteAtOffset(segment, 0L);
 604     }
 605 
 606     /**
 607      * Writes a byte at given segment.
 608      * <p>
 609      * This is equivalent to the following code:
 610      * <blockquote><pre>{@code
 611     setByteAtOffset(segment, 0L, value);
 612      * }</pre></blockquote>
 613      * @param segment the segment to be dereferenced.
 614      * @param value the byte value to be written.
 615      */
 616     @ForceInline
 617     public static void setByte(MemorySegment segment, byte value) {
 618         setByteAtOffset(segment, 0L, value);
 619     }
 620 
 621     /**
 622      * Reads a char from given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 623      * <p>
 624      * This is equivalent to the following code:
 625      * <blockquote><pre>{@code
 626     char value = getCharAtOffset(segment, 0L);
 627      * }</pre></blockquote>
 628      * @param segment the segment to be dereferenced.
 629      * @return a char value read from {@code segment}.
 630      */
 631     @ForceInline
 632     public static char getChar(MemorySegment segment) {
 633         return getCharAtOffset(segment, 0L);
 634     }
 635 
 636     /**
 637      * Writes a char at given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 638      * <p>
 639      * This is equivalent to the following code:
 640      * <blockquote><pre>{@code
 641     setCharAtOffset(segment, 0L, value);
 642      * }</pre></blockquote>
 643      * @param segment the segment to be dereferenced.
 644      * @param value the char value to be written.
 645      */
 646     @ForceInline
 647     public static void setChar(MemorySegment segment, char value) {
 648         setCharAtOffset(segment, 0L, value);
 649     }
 650 
 651     /**
 652      * Reads a short from given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 653      * <p>
 654      * This is equivalent to the following code:
 655      * <blockquote><pre>{@code
 656     short value = getShortAtOffset(segment, 0L);
 657      * }</pre></blockquote>
 658      * @param segment the segment to be dereferenced.
 659      * @return a short value read from {@code segment}.
 660      */
 661     @ForceInline
 662     public static short getShort(MemorySegment segment) {
 663         return getShortAtOffset(segment, 0L);
 664     }
 665 
 666     /**
 667      * Writes a short at given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 668      * <p>
 669      * This is equivalent to the following code:
 670      * <blockquote><pre>{@code
 671     setShortAtOffset(segment, 0L, value);
 672      * }</pre></blockquote>
 673      * @param segment the segment to be dereferenced.
 674      * @param value the short value to be written.
 675      */
 676     @ForceInline
 677     public static void setShort(MemorySegment segment, short value) {
 678         setShortAtOffset(segment, 0L, value);
 679     }
 680 
 681     /**
 682      * Reads an int from given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 683      * <p>
 684      * This is equivalent to the following code:
 685      * <blockquote><pre>{@code
 686     int value = getIntAtOffset(segment, 0L);
 687      * }</pre></blockquote>
 688      * @param segment the segment to be dereferenced.
 689      * @return an int value read from {@code segment}.
 690      */
 691     @ForceInline
 692     public static int getInt(MemorySegment segment) {
 693         return getIntAtOffset(segment, 0L);
 694     }
 695 
 696     /**
 697      * Writes an int at given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 698      * <p>
 699      * This is equivalent to the following code:
 700      * <blockquote><pre>{@code
 701     setIntAtOffset(segment, 0L, value);
 702      * }</pre></blockquote>
 703      * @param segment the segment to be dereferenced.
 704      * @param value the int value to be written.
 705      */
 706     @ForceInline
 707     public static void setInt(MemorySegment segment, int value) {
 708         setIntAtOffset(segment, 0L, value);
 709     }
 710 
 711     /**
 712      * Reads a float from given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 713      * <p>
 714      * This is equivalent to the following code:
 715      * <blockquote><pre>{@code
 716     float value = getFloatAtOffset(segment, 0L);
 717      * }</pre></blockquote>
 718      * @param segment the segment to be dereferenced.
 719      * @return a float value read from {@code segment}.
 720      */
 721     @ForceInline
 722     public static float getFloat(MemorySegment segment) {
 723         return getFloatAtOffset(segment, 0L);
 724     }
 725 
 726     /**
 727      * Writes a float at given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 728      * <p>
 729      * This is equivalent to the following code:
 730      * <blockquote><pre>{@code
 731     setFloatAtOffset(segment, 0L, value);
 732      * }</pre></blockquote>
 733      * @param segment the segment to be dereferenced.
 734      * @param value the float value to be written.
 735      */
 736     @ForceInline
 737     public static void setFloat(MemorySegment segment, float value) {
 738         setFloatAtOffset(segment, 0L, value);
 739     }
 740 
 741     /**
 742      * Reads a long from given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 743      * <p>
 744      * This is equivalent to the following code:
 745      * <blockquote><pre>{@code
 746     long value = getLongAtOffset(segment, 0L);
 747      * }</pre></blockquote>
 748      * @param segment the segment to be dereferenced.
 749      * @return a long value read from {@code segment}.
 750      */
 751     @ForceInline
 752     public static long getLong(MemorySegment segment) {
 753         return getLongAtOffset(segment, 0L);
 754     }
 755 
 756     /**
 757      * Writes a long at given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 758      * <p>
 759      * This is equivalent to the following code:
 760      * <blockquote><pre>{@code
 761     setLongAtOffset(segment, 0L, value);
 762      * }</pre></blockquote>
 763      * @param segment the segment to be dereferenced.
 764      * @param value the long value to be written.
 765      */
 766     @ForceInline
 767     public static void setLong(MemorySegment segment, long value) {
 768         setLongAtOffset(segment, 0L, value);
 769     }
 770 
 771     /**
 772      * Reads a double from given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 773      * <p>
 774      * This is equivalent to the following code:
 775      * <blockquote><pre>{@code
 776     double value = getDoubleAtOffset(segment, 0L);
 777      * }</pre></blockquote>
 778      * @param segment the segment to be dereferenced.
 779      * @return a double value read from {@code segment}.
 780      */
 781     @ForceInline
 782     public static double getDouble(MemorySegment segment) {
 783         return getDoubleAtOffset(segment, 0L);
 784     }
 785 
 786     /**
 787      * Writes a double at given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 788      * <p>
 789      * This is equivalent to the following code:
 790      * <blockquote><pre>{@code
 791     setDoubleAtOffset(segment, 0L, value);
 792      * }</pre></blockquote>
 793      * @param segment the segment to be dereferenced.
 794      * @param value the double value to be written.
 795      */
 796     @ForceInline
 797     public static void setDouble(MemorySegment segment, double value) {
 798         setDoubleAtOffset(segment, 0L, value);
 799     }
 800 
 801     /**
 802      * Reads a memory address from given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 803      * <p>
 804      * This is equivalent to the following code:
 805      * <blockquote><pre>{@code
 806     MemoryAddress value = getAddressAtOffset(segment, 0L);
 807      * }</pre></blockquote>
 808      * @param segment the segment to be dereferenced.
 809      * @return a memory address read from {@code segment}.
 810      */
 811     @ForceInline
 812     public static MemoryAddress getAddress(MemorySegment segment) {
 813         return getAddressAtOffset(segment, 0L);
 814     }
 815 
 816     /**
 817      * Writes a memory address at given segment, with byte order set to {@link ByteOrder#nativeOrder()}.
 818      * <p>
 819      * This is equivalent to the following code:
 820      * <blockquote><pre>{@code
 821     setAddressAtOffset(segment, 0L, value);
 822      * }</pre></blockquote>
 823      * @param segment the segment to be dereferenced.
 824      * @param value the memory address to be written (expressed as an {@link Addressable} instance).
 825      */
 826     @ForceInline
 827     public static void setAddress(MemorySegment segment, Addressable value) {
 828         setAddressAtOffset(segment, 0L, value);
 829     }
 830 
 831     /**
 832      * Reads a char from given segment, with given byte order.
 833      * <p>
 834      * This is equivalent to the following code:
 835      * <blockquote><pre>{@code
 836     char value = getCharAtOffset(segment, 0L, order);
 837      * }</pre></blockquote>
 838      * @param segment the segment to be dereferenced.
 839      * @param order the specified byte order.
 840      * @return a char value read from {@code segment}.
 841      */
 842     @ForceInline
 843     public static char getChar(MemorySegment segment, ByteOrder order) {
 844         return getCharAtOffset(segment, 0L, order);
 845     }
 846 
 847     /**
 848      * Writes a char at given segment, with given byte order.
 849      * <p>
 850      * This is equivalent to the following code:
 851      * <blockquote><pre>{@code
 852     setCharAtOffset(segment, 0L, order, value);
 853      * }</pre></blockquote>
 854      * @param segment the segment to be dereferenced.
 855      * @param order the specified byte order.
 856      * @param value the char value to be written.
 857      */
 858     @ForceInline
 859     public static void setChar(MemorySegment segment, ByteOrder order, char value) {
 860         setCharAtOffset(segment, 0L, order, value);
 861     }
 862 
 863     /**
 864      * Reads a short from given segment, with given byte order.
 865      * <p>
 866      * This is equivalent to the following code:
 867      * <blockquote><pre>{@code
 868     short value = getShortAtOffset(segment, 0L, order);
 869      * }</pre></blockquote>
 870      * @param segment the segment to be dereferenced.
 871      * @param order the specified byte order.
 872      * @return a short value read from {@code segment}.
 873      */
 874     @ForceInline
 875     public static short getShort(MemorySegment segment, ByteOrder order) {
 876         return getShortAtOffset(segment, 0L, order);
 877     }
 878 
 879     /**
 880      * Writes a short at given segment, with given byte order.
 881      * <p>
 882      * This is equivalent to the following code:
 883      * <blockquote><pre>{@code
 884     setShortAtOffset(segment, 0L, order, value);
 885      * }</pre></blockquote>
 886      * @param segment the segment to be dereferenced.
 887      * @param order the specified byte order.
 888      * @param value the short value to be written.
 889      */
 890     @ForceInline
 891     public static void setShort(MemorySegment segment, ByteOrder order, short value) {
 892         setShortAtOffset(segment, 0L, order, value);
 893     }
 894 
 895     /**
 896      * Reads an int from given segment, with given byte order.
 897      * <p>
 898      * This is equivalent to the following code:
 899      * <blockquote><pre>{@code
 900     int value = getIntAtOffset(segment, 0L, order);
 901      * }</pre></blockquote>
 902      * @param segment the segment to be dereferenced.
 903      * @param order the specified byte order.
 904      * @return an int value read from {@code segment}.
 905      */
 906     @ForceInline
 907     public static int getInt(MemorySegment segment, ByteOrder order) {
 908         return getIntAtOffset(segment, 0L, order);
 909     }
 910 
 911     /**
 912      * Writes an int at given segment, with given byte order.
 913      * <p>
 914      * This is equivalent to the following code:
 915      * <blockquote><pre>{@code
 916     setIntAtOffset(segment, 0L, order, value);
 917      * }</pre></blockquote>
 918      * @param segment the segment to be dereferenced.
 919      * @param order the specified byte order.
 920      * @param value the int value to be written.
 921      */
 922     @ForceInline
 923     public static void setInt(MemorySegment segment, ByteOrder order, int value) {
 924         setIntAtOffset(segment, 0L, order, value);
 925     }
 926 
 927     /**
 928      * Reads a float from given segment, with given byte order.
 929      * <p>
 930      * This is equivalent to the following code:
 931      * <blockquote><pre>{@code
 932     float value = getFloatAtOffset(segment, 0L, order);
 933      * }</pre></blockquote>
 934      * @param segment the segment to be dereferenced.
 935      * @param order the specified byte order.
 936      * @return a float value read from {@code segment}.
 937      */
 938     @ForceInline
 939     public static float getFloat(MemorySegment segment, ByteOrder order) {
 940         return getFloatAtOffset(segment, 0L, order);
 941     }
 942 
 943     /**
 944      * Writes a float at given segment, with given byte order.
 945      * <p>
 946      * This is equivalent to the following code:
 947      * <blockquote><pre>{@code
 948     setFloatAtOffset(segment, 0L, order, value);
 949      * }</pre></blockquote>
 950      * @param segment the segment to be dereferenced.
 951      * @param order the specified byte order.
 952      * @param value the float value to be written.
 953      */
 954     @ForceInline
 955     public static void setFloat(MemorySegment segment, ByteOrder order, float value) {
 956         setFloatAtOffset(segment, 0L, order, value);
 957     }
 958 
 959     /**
 960      * Reads a long from given segment, with given byte order.
 961      * <p>
 962      * This is equivalent to the following code:
 963      * <blockquote><pre>{@code
 964     long value = getLongAtOffset(segment, 0L, order);
 965      * }</pre></blockquote>
 966      * @param segment the segment to be dereferenced.
 967      * @param order the specified byte order.
 968      * @return a long value read from {@code segment}.
 969      */
 970     @ForceInline
 971     public static long getLong(MemorySegment segment, ByteOrder order) {
 972         return getLongAtOffset(segment, 0L, order);
 973     }
 974 
 975     /**
 976      * Writes a long at given segment, with given byte order.
 977      * <p>
 978      * This is equivalent to the following code:
 979      * <blockquote><pre>{@code
 980     setLongAtOffset(segment, 0L, order, value);
 981      * }</pre></blockquote>
 982      * @param segment the segment to be dereferenced.
 983      * @param order the specified byte order.
 984      * @param value the long value to be written.
 985      */
 986     @ForceInline
 987     public static void setLong(MemorySegment segment, ByteOrder order, long value) {
 988         setLongAtOffset(segment, 0L, order, value);
 989     }
 990 
 991     /**
 992      * Reads a double from given segment, with given byte order.
 993      * <p>
 994      * This is equivalent to the following code:
 995      * <blockquote><pre>{@code
 996     double value = getDoubleAtOffset(segment, 0L, order);
 997      * }</pre></blockquote>
 998      * @param segment the segment to be dereferenced.
 999      * @param order the specified byte order.
1000      * @return a double value read from {@code segment}.
1001      */
1002     @ForceInline
1003     public static double getDouble(MemorySegment segment, ByteOrder order) {
1004         return getDoubleAtOffset(segment, 0L, order);
1005     }
1006 
1007     /**
1008      * Writes a double at given segment, with given byte order.
1009      * <p>
1010      * This is equivalent to the following code:
1011      * <blockquote><pre>{@code
1012     setDoubleAtOffset(segment, 0L, order, value);
1013      * }</pre></blockquote>
1014      * @param segment the segment to be dereferenced.
1015      * @param order the specified byte order.
1016      * @param value the double value to be written.
1017      */
1018     @ForceInline
1019     public static void setDouble(MemorySegment segment, ByteOrder order, double value) {
1020         setDoubleAtOffset(segment, 0L, order, value);
1021     }
1022 
1023     /**
1024      * Reads a char from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1025      * <p>
1026      * This is equivalent to the following code:
1027      * <blockquote><pre>{@code
1028     char value = getCharAtOffset(segment, 2 * index);
1029      * }</pre></blockquote>
1030      * @param segment the segment to be dereferenced.
1031      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}.
1032      * @return a char value read from {@code segment} at the element index specified by {@code index}.
1033      */
1034     @ForceInline
1035     public static char getCharAtIndex(MemorySegment segment, long index) {
1036         return getCharAtOffset(segment, scale(segment, index, 2));
1037     }
1038 
1039     /**
1040      * Writes a char at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1041      * <p>
1042      * This is equivalent to the following code:
1043      * <blockquote><pre>{@code
1044     setCharAtOffset(segment, 2 * index, value);
1045      * }</pre></blockquote>
1046      * @param segment the segment to be dereferenced.
1047      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}.
1048      * @param value the char value to be written.
1049      */
1050     @ForceInline
1051     public static void setCharAtIndex(MemorySegment segment, long index, char value) {
1052         setCharAtOffset(segment, scale(segment, index, 2), value);
1053     }
1054 
1055     /**
1056      * Reads a short from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1057      * <p>
1058      * This is equivalent to the following code:
1059      * <blockquote><pre>{@code
1060     short value = getShortAtOffset(segment, 2 * index);
1061      * }</pre></blockquote>
1062      * @param segment the segment to be dereferenced.
1063      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}.
1064      * @return a short value read from {@code segment} at the element index specified by {@code index}.
1065      */
1066     @ForceInline
1067     public static short getShortAtIndex(MemorySegment segment, long index) {
1068         return getShortAtOffset(segment, scale(segment, index, 2));
1069     }
1070 
1071     /**
1072      * Writes a short at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1073      * <p>
1074      * This is equivalent to the following code:
1075      * <blockquote><pre>{@code
1076     setShortAtOffset(segment, 2 * index, value);
1077      * }</pre></blockquote>
1078      * @param segment the segment to be dereferenced.
1079      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}.
1080      * @param value the short value to be written.
1081      */
1082     @ForceInline
1083     public static void setShortAtIndex(MemorySegment segment, long index, short value) {
1084         setShortAtOffset(segment, scale(segment, index, 2), value);
1085     }
1086 
1087     /**
1088      * Reads an int from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1089      * <p>
1090      * This is equivalent to the following code:
1091      * <blockquote><pre>{@code
1092     int value = getIntAtOffset(segment, 4 * index);
1093      * }</pre></blockquote>
1094      * @param segment the segment to be dereferenced.
1095      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}.
1096      * @return an int value read from {@code segment} at the element index specified by {@code index}.
1097      */
1098     @ForceInline
1099     public static int getIntAtIndex(MemorySegment segment, long index) {
1100         return getIntAtOffset(segment, scale(segment, index, 4));
1101     }
1102 
1103     /**
1104      * Writes an int at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1105      * <p>
1106      * This is equivalent to the following code:
1107      * <blockquote><pre>{@code
1108     setIntAtOffset(segment, 4 * index, value);
1109      * }</pre></blockquote>
1110      * @param segment the segment to be dereferenced.
1111      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}.
1112      * @param value the int value to be written.
1113      */
1114     @ForceInline
1115     public static void setIntAtIndex(MemorySegment segment, long index, int value) {
1116         setIntAtOffset(segment, scale(segment, index, 4), value);
1117     }
1118 
1119     /**
1120      * Reads a float from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1121      * <p>
1122      * This is equivalent to the following code:
1123      * <blockquote><pre>{@code
1124     float value = getFloatAtOffset(segment, 4 * index);
1125      * }</pre></blockquote>
1126      * @param segment the segment to be dereferenced.
1127      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}.
1128      * @return a float value read from {@code segment} at the element index specified by {@code index}.
1129      */
1130     @ForceInline
1131     public static float getFloatAtIndex(MemorySegment segment, long index) {
1132         return getFloatAtOffset(segment, scale(segment, index, 4));
1133     }
1134 
1135     /**
1136      * Writes a float at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1137      * <p>
1138      * This is equivalent to the following code:
1139      * <blockquote><pre>{@code
1140     setFloatAtOffset(segment, 4 * index, value);
1141      * }</pre></blockquote>
1142      * @param segment the segment to be dereferenced.
1143      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}.
1144      * @param value the float value to be written.
1145      */
1146     @ForceInline
1147     public static void setFloatAtIndex(MemorySegment segment, long index, float value) {
1148         setFloatAtOffset(segment, scale(segment, index, 4), value);
1149     }
1150 
1151     /**
1152      * Reads a long from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1153      * <p>
1154      * This is equivalent to the following code:
1155      * <blockquote><pre>{@code
1156     return getLongAtOffset(segment, 8 * index);
1157      * }</pre></blockquote>
1158      * @param segment the segment to be dereferenced.
1159      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1160      * @return a long value read from {@code segment} at the element index specified by {@code index}.
1161      */
1162     @ForceInline
1163     public static long getLongAtIndex(MemorySegment segment, long index) {
1164         return getLongAtOffset(segment, scale(segment, index, 8));
1165     }
1166 
1167     /**
1168      * Writes a long at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1169      * <p>
1170      * This is equivalent to the following code:
1171      * <blockquote><pre>{@code
1172     setLongAtOffset(segment, 8 * index, value);
1173      * }</pre></blockquote>
1174      * @param segment the segment to be dereferenced.
1175      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1176      * @param value the long value to be written.
1177      */
1178     @ForceInline
1179     public static void setLongAtIndex(MemorySegment segment, long index, long value) {
1180         setLongAtOffset(segment, scale(segment, index, 8), value);
1181     }
1182 
1183     /**
1184      * Reads a double from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1185      * <p>
1186      * This is equivalent to the following code:
1187      * <blockquote><pre>{@code
1188     return getDoubleAtOffset(segment, 8 * index);
1189      * }</pre></blockquote>
1190      * @param segment the segment to be dereferenced.
1191      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1192      * @return a double value read from {@code segment} at the element index specified by {@code index}.
1193      */
1194     @ForceInline
1195     public static double getDoubleAtIndex(MemorySegment segment, long index) {
1196         return getDoubleAtOffset(segment, scale(segment, index, 8));
1197     }
1198 
1199     /**
1200      * Writes a double at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1201      * <p>
1202      * This is equivalent to the following code:
1203      * <blockquote><pre>{@code
1204     setDoubleAtOffset(segment, 8 * index, value);
1205      * }</pre></blockquote>
1206      * @param segment the segment to be dereferenced.
1207      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1208      * @param value the double value to be written.
1209      */
1210     @ForceInline
1211     public static void setDoubleAtIndex(MemorySegment segment, long index, double value) {
1212         setDoubleAtOffset(segment, scale(segment, index, 8), value);
1213     }
1214 
1215     /**
1216      * Reads a memory address from given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1217      * <p>
1218      * This is equivalent to the following code:
1219      * <blockquote><pre>{@code
1220     return getAddressAtOffset(segment, index * MemoryLayouts.ADDRESS.byteSize());
1221      * }</pre></blockquote>
1222      * @param segment the segment to be dereferenced.
1223      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1224      * @return a memory address read from {@code segment} at the element index specified by {@code index}.
1225      */
1226     @ForceInline
1227     public static MemoryAddress getAddressAtIndex(MemorySegment segment, long index) {
1228         return getAddressAtOffset(segment, scale(segment, index, (int)MemoryLayouts.ADDRESS.byteSize()));
1229     }
1230 
1231     /**
1232      * Writes a memory address at given segment and element index, with byte order set to {@link ByteOrder#nativeOrder()}.
1233      * <p>
1234      * This is equivalent to the following code:
1235      * <blockquote><pre>{@code
1236     setAddressAtOffset(segment, index * MemoryLayouts.ADDRESS.byteSize(), value);
1237      * }</pre></blockquote>
1238      * @param segment the segment to be dereferenced.
1239      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1240      * @param value the memory address to be written (expressed as an {@link Addressable} instance).
1241      */
1242     @ForceInline
1243     public static void setAddressAtIndex(MemorySegment segment, long index, Addressable value) {
1244         setAddressAtOffset(segment, scale(segment, index, (int)MemoryLayouts.ADDRESS.byteSize()), value);
1245     }
1246 
1247     /**
1248      * Reads a char from given segment and element index, with given byte order.
1249      * <p>
1250      * This is equivalent to the following code:
1251      * <blockquote><pre>{@code
1252     char value = getCharAtOffset(segment, 2 * index, order);
1253      * }</pre></blockquote>
1254      * @param segment the segment to be dereferenced.
1255      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}.
1256      * @param order the specified byte order.
1257      * @return a char value read from {@code segment} at the element index specified by {@code index}.
1258      */
1259     @ForceInline
1260     public static char getCharAtIndex(MemorySegment segment, long index, ByteOrder order) {
1261         return getCharAtOffset(segment, scale(segment, index, 2), order);
1262     }
1263 
1264     /**
1265      * Writes a char at given segment and element index, with given byte order.
1266      * <p>
1267      * This is equivalent to the following code:
1268      * <blockquote><pre>{@code
1269     setCharAtOffset(segment, 2 * index, order, value);
1270      * }</pre></blockquote>
1271      * @param segment the segment to be dereferenced.
1272      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}.
1273      * @param order the specified byte order.
1274      * @param value the char value to be written.
1275      */
1276     @ForceInline
1277     public static void setCharAtIndex(MemorySegment segment, long index, ByteOrder order, char value) {
1278         setCharAtOffset(segment, scale(segment, index, 2), order, value);
1279     }
1280 
1281     /**
1282      * Reads a short from given segment and element index, with given byte order.
1283      * <p>
1284      * This is equivalent to the following code:
1285      * <blockquote><pre>{@code
1286     short value = getShortAtOffset(segment, 2 * index, order);
1287      * }</pre></blockquote>
1288      * @param segment the segment to be dereferenced.
1289      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}.
1290      * @param order the specified byte order.
1291      * @return a short value read from {@code segment} at the element index specified by {@code index}.
1292      */
1293     @ForceInline
1294     public static short getShortAtIndex(MemorySegment segment, long index, ByteOrder order) {
1295         return getShortAtOffset(segment, scale(segment, index, 2), order);
1296     }
1297 
1298     /**
1299      * Writes a short at given segment and element index, with given byte order.
1300      * <p>
1301      * This is equivalent to the following code:
1302      * <blockquote><pre>{@code
1303     setShortAtOffset(segment, 2 * index, order, value);
1304      * }</pre></blockquote>
1305      * @param segment the segment to be dereferenced.
1306      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 2)}.
1307      * @param order the specified byte order.
1308      * @param value the short value to be written.
1309      */
1310     @ForceInline
1311     public static void setShortAtIndex(MemorySegment segment, long index, ByteOrder order, short value) {
1312         setShortAtOffset(segment, scale(segment, index, 2), order, value);
1313     }
1314 
1315     /**
1316      * Reads an int from given segment and element index, with given byte order.
1317      * <p>
1318      * This is equivalent to the following code:
1319      * <blockquote><pre>{@code
1320     int value = getIntAtOffset(segment, 4 * index, order);
1321      * }</pre></blockquote>
1322      * @param segment the segment to be dereferenced.
1323      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}.
1324      * @param order the specified byte order.
1325      * @return an int value read from {@code segment} at the element index specified by {@code index}.
1326      */
1327     @ForceInline
1328     public static int getIntAtIndex(MemorySegment segment, long index, ByteOrder order) {
1329         return getIntAtOffset(segment, scale(segment, index, 4), order);
1330     }
1331 
1332     /**
1333      * Writes an int at given segment and element index, with given byte order.
1334      * <p>
1335      * This is equivalent to the following code:
1336      * <blockquote><pre>{@code
1337     setIntAtOffset(segment, 4 * index, order, value);
1338      * }</pre></blockquote>
1339      * @param segment the segment to be dereferenced.
1340      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}.
1341      * @param order the specified byte order.
1342      * @param value the int value to be written.
1343      */
1344     @ForceInline
1345     public static void setIntAtIndex(MemorySegment segment, long index, ByteOrder order, int value) {
1346         setIntAtOffset(segment, scale(segment, index, 4), order, value);
1347     }
1348 
1349     /**
1350      * Reads a float from given segment and element index, with given byte order.
1351      * <p>
1352      * This is equivalent to the following code:
1353      * <blockquote><pre>{@code
1354     float value = getFloatAtOffset(segment, 4 * index, order);
1355      * }</pre></blockquote>
1356      * @param segment the segment to be dereferenced.
1357      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}.
1358      * @param order the specified byte order.
1359      * @return a float value read from {@code segment} at the element index specified by {@code index}.
1360      */
1361     @ForceInline
1362     public static float getFloatAtIndex(MemorySegment segment, long index, ByteOrder order) {
1363         return getFloatAtOffset(segment, scale(segment, index, 4), order);
1364     }
1365 
1366     /**
1367      * Writes a float at given segment and element index, with given byte order.
1368      * <p>
1369      * This is equivalent to the following code:
1370      * <blockquote><pre>{@code
1371     setFloatAtOffset(segment, 4 * index, order, value);
1372      * }</pre></blockquote>
1373      * @param segment the segment to be dereferenced.
1374      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 4)}.
1375      * @param order the specified byte order.
1376      * @param value the float value to be written.
1377      */
1378     @ForceInline
1379     public static void setFloatAtIndex(MemorySegment segment, long index, ByteOrder order, float value) {
1380         setFloatAtOffset(segment, scale(segment, index, 4), order, value);
1381     }
1382 
1383     /**
1384      * Reads a long from given segment and element index, with given byte order.
1385      * <p>
1386      * This is equivalent to the following code:
1387      * <blockquote><pre>{@code
1388     return getLongAtOffset(segment, 8 * index, order);
1389      * }</pre></blockquote>
1390      * @param segment the segment to be dereferenced.
1391      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1392      * @param order the specified byte order.
1393      * @return a long value read from {@code segment} at the element index specified by {@code index}.
1394      */
1395     @ForceInline
1396     public static long getLongAtIndex(MemorySegment segment, long index, ByteOrder order) {
1397         return getLongAtOffset(segment, scale(segment, index, 8), order);
1398     }
1399 
1400     /**
1401      * Writes a long at given segment and element index, with given byte order.
1402      * <p>
1403      * This is equivalent to the following code:
1404      * <blockquote><pre>{@code
1405     setLongAtOffset(segment, 8 * index, order, value);
1406      * }</pre></blockquote>
1407      * @param segment the segment to be dereferenced.
1408      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1409      * @param order the specified byte order.
1410      * @param value the long value to be written.
1411      */
1412     @ForceInline
1413     public static void setLongAtIndex(MemorySegment segment, long index, ByteOrder order, long value) {
1414         setLongAtOffset(segment, scale(segment, index, 8), order, value);
1415     }
1416 
1417     /**
1418      * Reads a double from given segment and element index, with given byte order.
1419      * <p>
1420      * This is equivalent to the following code:
1421      * <blockquote><pre>{@code
1422     return getDoubleAtOffset(segment, 8 * index, order);
1423      * }</pre></blockquote>
1424      * @param segment the segment to be dereferenced.
1425      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1426      * @param order the specified byte order.
1427      * @return a double value read from {@code segment} at the element index specified by {@code index}.
1428      */
1429     @ForceInline
1430     public static double getDoubleAtIndex(MemorySegment segment, long index, ByteOrder order) {
1431         return getDoubleAtOffset(segment, scale(segment, index, 8), order);
1432     }
1433 
1434     /**
1435      * Writes a double at given segment and element index, with given byte order.
1436      * <p>
1437      * This is equivalent to the following code:
1438      * <blockquote><pre>{@code
1439     setDoubleAtOffset(segment, 8 * index, order, value);
1440      * }</pre></blockquote>
1441      * @param segment the segment to be dereferenced.
1442      * @param index element index (relative to {@code segment}). The final address of this read operation can be expressed as {@code segment.address().addOffset(index * 8)}.
1443      * @param order the specified byte order.
1444      * @param value the double value to be written.
1445      */
1446     @ForceInline
1447     public static void setDoubleAtIndex(MemorySegment segment, long index, ByteOrder order, double value) {
1448         setDoubleAtOffset(segment, scale(segment, index, 8), order, value);
1449     }
1450 
1451     @ForceInline
1452     private static long scale(MemorySegment address, long index, int size) {
1453         return MemorySegmentProxy.multiplyOffsets(index, size, (MemorySegmentProxy)address);
1454     }
1455 }