< prev index next >

src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java

Print this page
*** 23,20 ***
   * questions.
   */
  
  package java.lang.foreign;
  
- import java.lang.invoke.VarHandle;
- import java.lang.reflect.Array;
  import java.nio.ByteOrder;
  import java.nio.charset.StandardCharsets;
  import java.util.Objects;
! import java.util.function.Function;
  import jdk.internal.foreign.AbstractMemorySegmentImpl;
  import jdk.internal.foreign.SlicingAllocator;
! import jdk.internal.foreign.Utils;
! import jdk.internal.javac.PreviewFeature;
  
  /**
   * An object that may be used to allocate {@linkplain MemorySegment memory segments}. Clients implementing this interface
   * must implement the {@link #allocate(long, long)} method. A segment allocator defines several methods
   * which can be useful to create segments from several kinds of Java values such as primitives and arrays.
--- 23,20 ---
   * questions.
   */
  
  package java.lang.foreign;
  
  import java.nio.ByteOrder;
+ import java.nio.charset.Charset;
  import java.nio.charset.StandardCharsets;
  import java.util.Objects;
! 
  import jdk.internal.foreign.AbstractMemorySegmentImpl;
+ import jdk.internal.foreign.ArenaImpl;
  import jdk.internal.foreign.SlicingAllocator;
! import jdk.internal.foreign.StringSupport;
! import jdk.internal.vm.annotation.ForceInline;
  
  /**
   * An object that may be used to allocate {@linkplain MemorySegment memory segments}. Clients implementing this interface
   * must implement the {@link #allocate(long, long)} method. A segment allocator defines several methods
   * which can be useful to create segments from several kinds of Java values such as primitives and arrays.

*** 68,36 ***
   * only interact with a segment allocator they own.
   * <p>
   * Clients should consider using an {@linkplain Arena arena} instead, which, provides strong thread-safety,
   * lifetime and non-overlapping guarantees.
   *
!  * @since 19
   */
  @FunctionalInterface
- @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
  public interface SegmentAllocator {
  
      /**
!      * {@return a new memory segment with a Java string converted into a UTF-8 encoded, null-terminated C string}
       * <p>
       * This method always replaces malformed-input and unmappable-character
       * sequences with this charset's default replacement byte array.  The
       * {@link java.nio.charset.CharsetEncoder} class should be used when more
       * control over the encoding process is required.
       * <p>
       * If the given string contains any {@code '\0'} characters, they will be
       * copied as well. This means that, depending on the method used to read
!      * the string, such as {@link MemorySegment#getUtf8String(long)}, the string
       * will appear truncated when read again.
       *
       * @implSpec The default implementation for this method copies the contents of the provided Java string
!      * into a new memory segment obtained by calling {@code this.allocate(str.length() + 1)}.
!      * @param str the Java string to be converted into a C string.
       */
!     default MemorySegment allocateUtf8String(String str) {
          Objects.requireNonNull(str);
!         return Utils.toCString(str.getBytes(StandardCharsets.UTF_8), this);
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code byte} {@code value} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
--- 68,72 ---
   * only interact with a segment allocator they own.
   * <p>
   * Clients should consider using an {@linkplain Arena arena} instead, which, provides strong thread-safety,
   * lifetime and non-overlapping guarantees.
   *
!  * @since 22
   */
  @FunctionalInterface
  public interface SegmentAllocator {
  
      /**
!      * Converts a Java string into a null-terminated C string using the {@linkplain StandardCharsets#UTF_8 UTF-8} charset,
+      * storing the result into a memory segment.
+      * <p>
+      * Calling this method is equivalent to the following code:
+      * {@snippet lang = java:
+      * allocateFrom(str, StandardCharsets.UTF_8);
+      *}
+      *
+      * @param str the Java string to be converted into a C string.
+      * @return a new native segment containing the converted C string.
+      */
+     @ForceInline
+     default MemorySegment allocateFrom(String str) {
+         Objects.requireNonNull(str);
+         return allocateFrom(str, StandardCharsets.UTF_8);
+     }
+ 
+     /**
+      * Converts a Java string into a null-terminated C string using the provided charset,
+      * and storing the result into a memory segment.
       * <p>
       * This method always replaces malformed-input and unmappable-character
       * sequences with this charset's default replacement byte array.  The
       * {@link java.nio.charset.CharsetEncoder} class should be used when more
       * control over the encoding process is required.
       * <p>
       * If the given string contains any {@code '\0'} characters, they will be
       * copied as well. This means that, depending on the method used to read
!      * the string, such as {@link MemorySegment#getString(long)}, the string
       * will appear truncated when read again.
       *
+      * @param str     the Java string to be converted into a C string.
+      * @param charset the charset used to {@linkplain Charset#newEncoder() encode} the string bytes.
+      * @return a new native segment containing the converted C string.
+      * @throws UnsupportedOperationException if {@code charset} is not a {@linkplain StandardCharsets standard charset}.
       * @implSpec The default implementation for this method copies the contents of the provided Java string
!      * into a new memory segment obtained by calling {@code this.allocate(B + N)}, where:
!      * <ul>
+      *     <li>{@code B} is the size, in bytes, of the string encoded using the provided charset
+      *     (e.g. {@code str.getBytes(charset).length});</li>
+      *     <li>{@code N} is the size (in bytes) of the terminator char according to the provided charset. For instance,
+      *     this is 1 for {@link StandardCharsets#US_ASCII} and 2 for {@link StandardCharsets#UTF_16}.</li>
+      * </ul>
       */
!     @ForceInline
+     default MemorySegment allocateFrom(String str, Charset charset) {
+         Objects.requireNonNull(charset);
          Objects.requireNonNull(str);
!         int termCharSize = StringSupport.CharsetKind.of(charset).terminatorCharSize();
+         byte[] bytes = str.getBytes(charset);
+         MemorySegment segment = allocateNoInit(bytes.length + termCharSize);
+         MemorySegment.copy(bytes, 0, segment, ValueLayout.JAVA_BYTE, 0, bytes.length);
+         for (int i = 0 ; i < termCharSize ; i++) {
+             segment.set(ValueLayout.JAVA_BYTE, bytes.length + i, (byte)0);
+         }
+         return segment;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code byte} {@code value} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}

*** 110,15 ***
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocate(ValueLayout.OfByte layout, byte value) {
          Objects.requireNonNull(layout);
!         VarHandle handle = layout.varHandle();
!         MemorySegment seg = allocate(layout);
-         handle.set(seg, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code char} {@code value} as
--- 146,14 ---
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocateFrom(ValueLayout.OfByte layout, byte value) {
          Objects.requireNonNull(layout);
!         MemorySegment seg = allocateNoInit(layout);
!         seg.set(layout, 0, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code char} {@code value} as

*** 132,15 ***
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocate(ValueLayout.OfChar layout, char value) {
          Objects.requireNonNull(layout);
!         VarHandle handle = layout.varHandle();
!         MemorySegment seg = allocate(layout);
-         handle.set(seg, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code short} {@code value} as
--- 167,14 ---
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocateFrom(ValueLayout.OfChar layout, char value) {
          Objects.requireNonNull(layout);
!         MemorySegment seg = allocateNoInit(layout);
!         seg.set(layout, 0, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code short} {@code value} as

*** 154,15 ***
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocate(ValueLayout.OfShort layout, short value) {
          Objects.requireNonNull(layout);
!         VarHandle handle = layout.varHandle();
!         MemorySegment seg = allocate(layout);
-         handle.set(seg, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code int} {@code value} as
--- 188,14 ---
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocateFrom(ValueLayout.OfShort layout, short value) {
          Objects.requireNonNull(layout);
!         MemorySegment seg = allocateNoInit(layout);
!         seg.set(layout, 0, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code int} {@code value} as

*** 176,15 ***
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocate(ValueLayout.OfInt layout, int value) {
          Objects.requireNonNull(layout);
!         VarHandle handle = layout.varHandle();
!         MemorySegment seg = allocate(layout);
-         handle.set(seg, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code float} {@code value} as
--- 209,14 ---
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocateFrom(ValueLayout.OfInt layout, int value) {
          Objects.requireNonNull(layout);
!         MemorySegment seg = allocateNoInit(layout);
!         seg.set(layout, 0, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code float} {@code value} as

*** 198,15 ***
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocate(ValueLayout.OfFloat layout, float value) {
          Objects.requireNonNull(layout);
!         VarHandle handle = layout.varHandle();
!         MemorySegment seg = allocate(layout);
-         handle.set(seg, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code long} {@code value} as
--- 230,14 ---
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocateFrom(ValueLayout.OfFloat layout, float value) {
          Objects.requireNonNull(layout);
!         MemorySegment seg = allocateNoInit(layout);
!         seg.set(layout, 0, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code long} {@code value} as

*** 220,15 ***
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocate(ValueLayout.OfLong layout, long value) {
          Objects.requireNonNull(layout);
!         VarHandle handle = layout.varHandle();
!         MemorySegment seg = allocate(layout);
-         handle.set(seg, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code double} {@code value} as
--- 251,14 ---
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocateFrom(ValueLayout.OfLong layout, long value) {
          Objects.requireNonNull(layout);
!         MemorySegment seg = allocateNoInit(layout);
!         seg.set(layout, 0, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the provided {@code double} {@code value} as

*** 242,15 ***
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocate(ValueLayout.OfDouble layout, double value) {
          Objects.requireNonNull(layout);
!         VarHandle handle = layout.varHandle();
!         MemorySegment seg = allocate(layout);
-         handle.set(seg, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the address of the provided {@code value} as
--- 272,14 ---
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocateFrom(ValueLayout.OfDouble layout, double value) {
          Objects.requireNonNull(layout);
!         MemorySegment seg = allocateNoInit(layout);
!         seg.set(layout, 0, value);
          return seg;
      }
  
      /**
       * {@return a new memory segment initialized with the address of the provided {@code value} as

*** 267,167 ***
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocate(AddressLayout layout, MemorySegment value) {
          Objects.requireNonNull(value);
          Objects.requireNonNull(layout);
!         MemorySegment seg = allocate(layout);
!         layout.varHandle().set(seg, value);
!         return seg;
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code byte} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec The default implementation is equivalent to:
!      * {@snippet lang=java :
!      *  int size = Objects.requireNonNull(elements).length;
!      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
!      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
-      *  return seg;
-      * }
-      *
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the short elements to be copied to the newly allocated memory block.
       */
!     default MemorySegment allocateArray(ValueLayout.OfByte elementLayout, byte... elements) {
!         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code short} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec The default implementation is equivalent to:
!      * {@snippet lang=java :
!      *  int size = Objects.requireNonNull(elements).length;
!      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
!      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
-      *  return seg;
-      * }
-      *
       * @param elementLayout the element layout of the array to be allocated.
       * @param elements      the short elements to be copied to the newly allocated memory block.
       */
!     default MemorySegment allocateArray(ValueLayout.OfShort elementLayout, short... elements) {
!         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code char} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec The default implementation is equivalent to:
!      * {@snippet lang=java :
!      *  int size = Objects.requireNonNull(elements).length;
!      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
!      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
-      *  return seg;
-      * }
-      *
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the short elements to be copied to the newly allocated memory block.
       */
!     default MemorySegment allocateArray(ValueLayout.OfChar elementLayout, char... elements) {
!         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code int} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec The default implementation is equivalent to:
!      * {@snippet lang=java :
!      *  int size = Objects.requireNonNull(elements).length;
!      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
!      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
-      *  return seg;
-      * }
-      *
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the short elements to be copied to the newly allocated memory block.
       */
!     default MemorySegment allocateArray(ValueLayout.OfInt elementLayout, int... elements) {
!         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code float} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec The default implementation is equivalent to:
!      * {@snippet lang=java :
!      *  int size = Objects.requireNonNull(elements).length;
!      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
!      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
-      *  return seg;
-      * }
-      *
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the short elements to be copied to the newly allocated memory block.
       */
!     default MemorySegment allocateArray(ValueLayout.OfFloat elementLayout, float... elements) {
!         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code long} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec The default implementation is equivalent to:
!      * {@snippet lang=java :
!      *  int size = Objects.requireNonNull(elements).length;
!      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
!      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
-      *  return seg;
-      * }
-      *
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the short elements to be copied to the newly allocated memory block.
       */
!     default MemorySegment allocateArray(ValueLayout.OfLong elementLayout, long... elements) {
!         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code double} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec The default implementation is equivalent to:
!      * {@snippet lang=java :
!      *  int size = Objects.requireNonNull(elements).length;
!      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
!      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
-      *  return seg;
-      * }
-      *
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the short elements to be copied to the newly allocated memory block.
       */
!     default MemorySegment allocateArray(ValueLayout.OfDouble elementLayout, double... elements) {
!         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);
!     }
! 
-     private <Z> MemorySegment copyArrayWithSwapIfNeeded(Z array, ValueLayout elementLayout,
-                                                         Function<Z, MemorySegment> heapSegmentFactory) {
-         int size = Array.getLength(Objects.requireNonNull(array));
-         MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
-         if (size > 0) {
-             MemorySegment.copy(heapSegmentFactory.apply(array), elementLayout, 0,
-                     seg, elementLayout.withOrder(ByteOrder.nativeOrder()), 0, size);
-         }
-         return seg;
      }
  
      /**
       * {@return a new memory segment with the given layout}
       *
--- 296,196 ---
       * }
       *
       * @param layout the layout of the block of memory to be allocated.
       * @param value  the value to be set in the newly allocated memory segment.
       */
!     default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) {
          Objects.requireNonNull(value);
          Objects.requireNonNull(layout);
!         MemorySegment segment = allocateNoInit(layout);
!         segment.set(layout, 0, value);
!         return segment;
+     }
+ 
+     /**
+      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
+      * {@code elementCount*elementLayout.byteSize()} initialized with the contents of the provided {@code source} segment
+      * as specified by the provided {@code elementLayout} (i.e. byte ordering, alignment and size)}
+      *
+      * @implSpec the default implementation for this method is equivalent to the following code:
+      * {@snippet lang = java:
+      * MemorySegment dest = this.allocate(elementLayout, elementCount);
+      * MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount);
+      * return dest;
+      * }
+      * @param elementLayout the element layout of the allocated array.
+      * @param source the source segment.
+      * @param sourceElementLayout the element layout of the source segment.
+      * @param sourceOffset the starting offset, in bytes, of the source segment.
+      * @param elementCount the number of elements in the source segment to be copied.
+      * @throws IllegalArgumentException if {@code elementLayout.byteSize() != sourceElementLayout.byteSize()}.
+      * @throws IllegalArgumentException if the source segment/offset are <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
+      * in the source element layout.
+      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
+      * @throws IllegalArgumentException if {@code sourceElementLayout.byteAlignment() > sourceElementLayout.byteSize()}.
+      * @throws IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated with {@code source} is not
+      * {@linkplain MemorySegment.Scope#isAlive() alive}.
+      * @throws WrongThreadException if this method is called from a thread {@code T},
+      * such that {@code source.isAccessibleBy(T) == false}.
+      * @throws IndexOutOfBoundsException if {@code elementCount * sourceElementLayout.byteSize()} overflows.
+      * @throws IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())}.
+      * @throws IndexOutOfBoundsException if either {@code sourceOffset} or {@code elementCount} are {@code < 0}.
+      */
+     @ForceInline
+     default MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source,
+                                        ValueLayout sourceElementLayout, long sourceOffset, long elementCount) {
+         Objects.requireNonNull(source);
+         Objects.requireNonNull(sourceElementLayout);
+         Objects.requireNonNull(elementLayout);
+         MemorySegment dest = allocateNoInit(elementLayout, elementCount);
+         MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount);
+         return dest;
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code byte} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec the default implementation for this method is equivalent to the following code:
!      * {@snippet lang = java:
!      * this.allocateFrom(layout, MemorySegment.ofArray(array),
!      *                   ValueLayout.JAVA_BYTE, 0, array.length)
!      *}
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the byte elements to be copied to the newly allocated memory block.
+      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
       */
!     @ForceInline
!     default MemorySegment allocateFrom(ValueLayout.OfByte elementLayout, byte... elements) {
+         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
+                 ValueLayout.JAVA_BYTE, 0, elements.length);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code short} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec the default implementation for this method is equivalent to the following code:
!      * {@snippet lang = java:
!      * this.allocateFrom(layout, MemorySegment.ofArray(array),
!      *                   ValueLayout.JAVA_SHORT, 0, array.length)
!      *}
       * @param elementLayout the element layout of the array to be allocated.
       * @param elements      the short elements to be copied to the newly allocated memory block.
+      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
       */
!     @ForceInline
!     default MemorySegment allocateFrom(ValueLayout.OfShort elementLayout, short... elements) {
+         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
+                 ValueLayout.JAVA_SHORT, 0, elements.length);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code char} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec the default implementation for this method is equivalent to the following code:
!      * {@snippet lang = java:
!      * this.allocateFrom(layout, MemorySegment.ofArray(array),
!      *                   ValueLayout.JAVA_CHAR, 0, array.length)
!      *}
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the char elements to be copied to the newly allocated memory block.
+      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
       */
!     @ForceInline
!     default MemorySegment allocateFrom(ValueLayout.OfChar elementLayout, char... elements) {
+         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
+                 ValueLayout.JAVA_CHAR, 0, elements.length);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code int} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec the default implementation for this method is equivalent to the following code:
!      * {@snippet lang = java:
!      * this.allocateFrom(layout, MemorySegment.ofArray(array),
!      *                   ValueLayout.JAVA_INT, 0, array.length)
!      *}
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the int elements to be copied to the newly allocated memory block.
+      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
       */
!     @ForceInline
!     default MemorySegment allocateFrom(ValueLayout.OfInt elementLayout, int... elements) {
+         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
+                 ValueLayout.JAVA_INT, 0, elements.length);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code float} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec the default implementation for this method is equivalent to the following code:
!      * {@snippet lang = java:
!      * this.allocateFrom(layout, MemorySegment.ofArray(array),
!      *                   ValueLayout.JAVA_FLOAT, 0, array.length)
!      *}
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements the float elements to be copied to the newly allocated memory block.
+      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
       */
!     @ForceInline
!     default MemorySegment allocateFrom(ValueLayout.OfFloat elementLayout, float... elements) {
+         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
+                 ValueLayout.JAVA_FLOAT, 0, elements.length);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code long} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec the default implementation for this method is equivalent to the following code:
!      * {@snippet lang = java:
!      * this.allocateFrom(layout, MemorySegment.ofArray(array),
!      *                   ValueLayout.JAVA_LONG, 0, array.length)
!      *}
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements the long elements to be copied to the newly allocated memory block.
+      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
       */
!     @ForceInline
!     default MemorySegment allocateFrom(ValueLayout.OfLong elementLayout, long... elements) {
+         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
+                 ValueLayout.JAVA_LONG, 0, elements.length);
      }
  
      /**
       * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
       * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code double} {@code elements} as
       * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
       *
!      * @implSpec the default implementation for this method is equivalent to the following code:
!      * {@snippet lang = java:
!      * this.allocateFrom(layout, MemorySegment.ofArray(array),
!      *                   ValueLayout.JAVA_DOUBLE, 0, array.length)
!      *}
       * @param elementLayout the element layout of the array to be allocated.
!      * @param elements      the double elements to be copied to the newly allocated memory block.
+      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
       */
!     @ForceInline
!     default MemorySegment allocateFrom(ValueLayout.OfDouble elementLayout, double... elements) {
!         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
!                 ValueLayout.JAVA_DOUBLE, 0, elements.length);
      }
  
      /**
       * {@return a new memory segment with the given layout}
       *

*** 450,11 ***
       * @param elementLayout the array element layout.
       * @param count the array element count.
       * @throws IllegalArgumentException if {@code elementLayout.byteSize() * count} overflows.
       * @throws IllegalArgumentException if {@code count < 0}.
       */
!     default MemorySegment allocateArray(MemoryLayout elementLayout, long count) {
          Objects.requireNonNull(elementLayout);
          if (count < 0) {
              throw new IllegalArgumentException("Negative array size");
          }
          return allocate(MemoryLayout.sequenceLayout(count, elementLayout));
--- 508,11 ---
       * @param elementLayout the array element layout.
       * @param count the array element count.
       * @throws IllegalArgumentException if {@code elementLayout.byteSize() * count} overflows.
       * @throws IllegalArgumentException if {@code count < 0}.
       */
!     default MemorySegment allocate(MemoryLayout elementLayout, long count) {
          Objects.requireNonNull(elementLayout);
          if (count < 0) {
              throw new IllegalArgumentException("Negative array size");
          }
          return allocate(MemoryLayout.sequenceLayout(count, elementLayout));

*** 523,6 ***
--- 581,27 ---
       * @return an allocator which recycles an existing segment upon each new allocation request.
       */
      static SegmentAllocator prefixAllocator(MemorySegment segment) {
          return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment);
      }
+ 
+     @ForceInline
+     private MemorySegment allocateNoInit(long byteSize) {
+         return this instanceof ArenaImpl arenaImpl ?
+                 arenaImpl.allocateNoInit(byteSize, 1) :
+                 allocate(byteSize);
+     }
+ 
+     @ForceInline
+     private MemorySegment allocateNoInit(MemoryLayout layout) {
+         return this instanceof ArenaImpl arenaImpl ?
+                 arenaImpl.allocateNoInit(layout.byteSize(), layout.byteAlignment()) :
+                 allocate(layout);
+     }
+ 
+     @ForceInline
+     private MemorySegment allocateNoInit(MemoryLayout layout, long size) {
+         return this instanceof ArenaImpl arenaImpl ?
+                 arenaImpl.allocateNoInit(layout.byteSize() * size, layout.byteAlignment()) :
+                 allocate(layout, size);
+     }
  }
< prev index next >