1 /*
  2  * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.foreign;
 27 
 28 import java.nio.ByteOrder;
 29 import java.nio.charset.Charset;
 30 import java.nio.charset.StandardCharsets;
 31 import java.util.Objects;
 32 
 33 import jdk.internal.foreign.AbstractMemorySegmentImpl;
 34 import jdk.internal.foreign.ArenaImpl;
 35 import jdk.internal.foreign.SlicingAllocator;
 36 import jdk.internal.foreign.StringSupport;
 37 import jdk.internal.vm.annotation.ForceInline;
 38 
 39 /**
 40  * An object that may be used to allocate {@linkplain MemorySegment memory segments}. Clients implementing this interface
 41  * must implement the {@link #allocate(long, long)} method. A segment allocator defines several methods
 42  * which can be useful to create segments from several kinds of Java values such as primitives and arrays.
 43  * <p>
 44  * {@code SegmentAllocator} is a {@linkplain FunctionalInterface functional interface}. Clients can easily obtain a new
 45  * segment allocator by using either a lambda expression or a method reference:
 46  *
 47  * {@snippet lang=java :
 48  * SegmentAllocator autoAllocator = (byteSize, byteAlignment) -> Arena.ofAuto().allocate(byteSize, byteAlignment);
 49  * }
 50  * <p>
 51  * This interface defines factories for commonly used allocators:
 52  * <ul>
 53  *     <li>{@link #slicingAllocator(MemorySegment)} obtains an efficient slicing allocator, where memory
 54  *     is allocated by repeatedly slicing the provided memory segment;</li>
 55  *     <li>{@link #prefixAllocator(MemorySegment)} obtains an allocator which wraps a segment
 56  *     and recycles its content upon each new allocation request.</li>
 57  * </ul>
 58  * <p>
 59  * Passing a segment allocator to an API can be especially useful in circumstances where a client wants to communicate <em>where</em>
 60  * the results of a certain operation (performed by the API) should be stored, as a memory segment. For instance,
 61  * {@linkplain Linker#downcallHandle(FunctionDescriptor, Linker.Option...) downcall method handles} can accept an additional
 62  * {@link SegmentAllocator} parameter if the underlying foreign function is known to return a struct by-value. Effectively,
 63  * the allocator parameter tells the linker where to store the return value of the foreign function.
 64  *
 65  * @apiNote Unless otherwise specified, the {@link #allocate(long, long)} method is not thread-safe.
 66  * Furthermore, memory segments allocated by a segment allocator can be associated with different
 67  * lifetimes, and can even be backed by overlapping regions of memory. For these reasons, clients should generally
 68  * only interact with a segment allocator they own.
 69  * <p>
 70  * Clients should consider using an {@linkplain Arena arena} instead, which, provides strong thread-safety,
 71  * lifetime and non-overlapping guarantees.
 72  *
 73  * @since 22
 74  */
 75 @FunctionalInterface
 76 public interface SegmentAllocator {
 77 
 78     /**
 79      * Converts a Java string into a null-terminated C string using the {@linkplain StandardCharsets#UTF_8 UTF-8} charset,
 80      * storing the result into a memory segment.
 81      * <p>
 82      * Calling this method is equivalent to the following code:
 83      * {@snippet lang = java:
 84      * allocateFrom(str, StandardCharsets.UTF_8);
 85      *}
 86      *
 87      * @param str the Java string to be converted into a C string.
 88      * @return a new native segment containing the converted C string.
 89      */
 90     @ForceInline
 91     default MemorySegment allocateFrom(String str) {
 92         Objects.requireNonNull(str);
 93         return allocateFrom(str, StandardCharsets.UTF_8);
 94     }
 95 
 96     /**
 97      * Converts a Java string into a null-terminated C string using the provided charset,
 98      * and storing the result into a memory segment.
 99      * <p>
100      * This method always replaces malformed-input and unmappable-character
101      * sequences with this charset's default replacement byte array.  The
102      * {@link java.nio.charset.CharsetEncoder} class should be used when more
103      * control over the encoding process is required.
104      * <p>
105      * If the given string contains any {@code '\0'} characters, they will be
106      * copied as well. This means that, depending on the method used to read
107      * the string, such as {@link MemorySegment#getString(long)}, the string
108      * will appear truncated when read again.
109      *
110      * @param str     the Java string to be converted into a C string.
111      * @param charset the charset used to {@linkplain Charset#newEncoder() encode} the string bytes.
112      * @return a new native segment containing the converted C string.
113      * @throws UnsupportedOperationException if {@code charset} is not a {@linkplain StandardCharsets standard charset}.
114      * @implSpec The default implementation for this method copies the contents of the provided Java string
115      * into a new memory segment obtained by calling {@code this.allocate(B + N)}, where:
116      * <ul>
117      *     <li>{@code B} is the size, in bytes, of the string encoded using the provided charset
118      *     (e.g. {@code str.getBytes(charset).length});</li>
119      *     <li>{@code N} is the size (in bytes) of the terminator char according to the provided charset. For instance,
120      *     this is 1 for {@link StandardCharsets#US_ASCII} and 2 for {@link StandardCharsets#UTF_16}.</li>
121      * </ul>
122      */
123     @ForceInline
124     default MemorySegment allocateFrom(String str, Charset charset) {
125         Objects.requireNonNull(charset);
126         Objects.requireNonNull(str);
127         int termCharSize = StringSupport.CharsetKind.of(charset).terminatorCharSize();
128         byte[] bytes = str.getBytes(charset);
129         MemorySegment segment = allocateNoInit(bytes.length + termCharSize);
130         MemorySegment.copy(bytes, 0, segment, ValueLayout.JAVA_BYTE, 0, bytes.length);
131         for (int i = 0 ; i < termCharSize ; i++) {
132             segment.set(ValueLayout.JAVA_BYTE, bytes.length + i, (byte)0);
133         }
134         return segment;
135     }
136 
137     /**
138      * {@return a new memory segment initialized with the provided {@code byte} {@code value} as
139      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
140      *
141      * @implSpec The default implementation is equivalent to:
142      * {@snippet lang=java :
143      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
144      *  seg.set(layout, 0, value);
145      *  return seg;
146      * }
147      *
148      * @param layout the layout of the block of memory to be allocated.
149      * @param value  the value to be set in the newly allocated memory segment.
150      */
151     default MemorySegment allocateFrom(ValueLayout.OfByte layout, byte value) {
152         Objects.requireNonNull(layout);
153         MemorySegment seg = allocateNoInit(layout);
154         seg.set(layout, 0, value);
155         return seg;
156     }
157 
158     /**
159      * {@return a new memory segment initialized with the provided {@code char} {@code value} as
160      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
161      *
162      * @implSpec The default implementation is equivalent to:
163      * {@snippet lang=java :
164      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
165      *  seg.set(layout, 0, value);
166      *  return seg;
167      * }
168      *
169      * @param layout the layout of the block of memory to be allocated.
170      * @param value  the value to be set in the newly allocated memory segment.
171      */
172     default MemorySegment allocateFrom(ValueLayout.OfChar layout, char value) {
173         Objects.requireNonNull(layout);
174         MemorySegment seg = allocateNoInit(layout);
175         seg.set(layout, 0, value);
176         return seg;
177     }
178 
179     /**
180      * {@return a new memory segment initialized with the provided {@code short} {@code value} as
181      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
182      *
183      * @implSpec The default implementation is equivalent to:
184      * {@snippet lang=java :
185      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
186      *  seg.set(layout, 0, value);
187      *  return seg;
188      * }
189      *
190      * @param layout the layout of the block of memory to be allocated.
191      * @param value  the value to be set in the newly allocated memory segment.
192      */
193     default MemorySegment allocateFrom(ValueLayout.OfShort layout, short value) {
194         Objects.requireNonNull(layout);
195         MemorySegment seg = allocateNoInit(layout);
196         seg.set(layout, 0, value);
197         return seg;
198     }
199 
200     /**
201      * {@return a new memory segment initialized with the provided {@code int} {@code value} as
202      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
203      *
204      * @implSpec The default implementation is equivalent to:
205      * {@snippet lang=java :
206      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
207      *  seg.set(layout, 0, value);
208      *  return seg;
209      * }
210      *
211      * @param layout the layout of the block of memory to be allocated.
212      * @param value  the value to be set in the newly allocated memory segment.
213      */
214     default MemorySegment allocateFrom(ValueLayout.OfInt layout, int value) {
215         Objects.requireNonNull(layout);
216         MemorySegment seg = allocateNoInit(layout);
217         seg.set(layout, 0, value);
218         return seg;
219     }
220 
221     /**
222      * {@return a new memory segment initialized with the provided {@code float} {@code value} as
223      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
224      *
225      * @implSpec The default implementation is equivalent to:
226      * {@snippet lang=java :
227      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
228      *  seg.set(layout, 0, value);
229      *  return seg;
230      * }
231      *
232      * @param layout the layout of the block of memory to be allocated.
233      * @param value  the value to be set in the newly allocated memory segment.
234      */
235     default MemorySegment allocateFrom(ValueLayout.OfFloat layout, float value) {
236         Objects.requireNonNull(layout);
237         MemorySegment seg = allocateNoInit(layout);
238         seg.set(layout, 0, value);
239         return seg;
240     }
241 
242     /**
243      * {@return a new memory segment initialized with the provided {@code long} {@code value} as
244      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
245      *
246      * @implSpec The default implementation is equivalent to:
247      * {@snippet lang=java :
248      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
249      *  seg.set(layout, 0, value);
250      *  return seg;
251      * }
252      *
253      * @param layout the layout of the block of memory to be allocated.
254      * @param value  the value to be set in the newly allocated memory segment.
255      */
256     default MemorySegment allocateFrom(ValueLayout.OfLong layout, long value) {
257         Objects.requireNonNull(layout);
258         MemorySegment seg = allocateNoInit(layout);
259         seg.set(layout, 0, value);
260         return seg;
261     }
262 
263     /**
264      * {@return a new memory segment initialized with the provided {@code double} {@code value} as
265      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
266      *
267      * @implSpec The default implementation is equivalent to:
268      * {@snippet lang=java :
269      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
270      *  seg.set(layout, 0, value);
271      *  return seg;
272      * }
273      *
274      * @param layout the layout of the block of memory to be allocated.
275      * @param value  the value to be set in the newly allocated memory segment.
276      */
277     default MemorySegment allocateFrom(ValueLayout.OfDouble layout, double value) {
278         Objects.requireNonNull(layout);
279         MemorySegment seg = allocateNoInit(layout);
280         seg.set(layout, 0, value);
281         return seg;
282     }
283 
284     /**
285      * {@return a new memory segment initialized with the address of the provided {@code value} as
286      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
287      * <p>
288      * The address value might be narrowed according to the platform address size (see {@link ValueLayout#ADDRESS}).
289      *
290      * @implSpec The default implementation is equivalent to:
291      * {@snippet lang=java :
292      *  Objects.requireNonNull(value);
293      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
294      *  seg.set(layout, 0, value);
295      *  return seg;
296      * }
297      *
298      * @param layout the layout of the block of memory to be allocated.
299      * @param value  the value to be set in the newly allocated memory segment.
300      */
301     default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) {
302         Objects.requireNonNull(value);
303         Objects.requireNonNull(layout);
304         MemorySegment segment = allocateNoInit(layout);
305         segment.set(layout, 0, value);
306         return segment;
307     }
308 
309     /**
310      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
311      * {@code elementCount*elementLayout.byteSize()} initialized with the contents of the provided {@code source} segment
312      * as specified by the provided {@code elementLayout} (i.e. byte ordering, alignment and size)}
313      *
314      * @implSpec the default implementation for this method is equivalent to the following code:
315      * {@snippet lang = java:
316      * MemorySegment dest = this.allocate(elementLayout, elementCount);
317      * MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount);
318      * return dest;
319      * }
320      * @param elementLayout the element layout of the allocated array.
321      * @param source the source segment.
322      * @param sourceElementLayout the element layout of the source segment.
323      * @param sourceOffset the starting offset, in bytes, of the source segment.
324      * @param elementCount the number of elements in the source segment to be copied.
325      * @throws IllegalArgumentException if {@code elementLayout.byteSize() != sourceElementLayout.byteSize()}.
326      * @throws IllegalArgumentException if the source segment/offset are <a href="MemorySegment.html#segment-alignment">incompatible with the alignment constraint</a>
327      * in the source element layout.
328      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
329      * @throws IllegalArgumentException if {@code sourceElementLayout.byteAlignment() > sourceElementLayout.byteSize()}.
330      * @throws IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated with {@code source} is not
331      * {@linkplain MemorySegment.Scope#isAlive() alive}.
332      * @throws WrongThreadException if this method is called from a thread {@code T},
333      * such that {@code source.isAccessibleBy(T) == false}.
334      * @throws IndexOutOfBoundsException if {@code elementCount * sourceElementLayout.byteSize()} overflows.
335      * @throws IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())}.
336      * @throws IndexOutOfBoundsException if either {@code sourceOffset} or {@code elementCount} are {@code < 0}.
337      */
338     @ForceInline
339     default MemorySegment allocateFrom(ValueLayout elementLayout, MemorySegment source,
340                                        ValueLayout sourceElementLayout, long sourceOffset, long elementCount) {
341         Objects.requireNonNull(source);
342         Objects.requireNonNull(sourceElementLayout);
343         Objects.requireNonNull(elementLayout);
344         MemorySegment dest = allocateNoInit(elementLayout, elementCount);
345         MemorySegment.copy(source, sourceElementLayout, sourceOffset, dest, elementLayout, 0, elementCount);
346         return dest;
347     }
348 
349     /**
350      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
351      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code byte} {@code elements} as
352      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
353      *
354      * @implSpec the default implementation for this method is equivalent to the following code:
355      * {@snippet lang = java:
356      * this.allocateFrom(layout, MemorySegment.ofArray(array),
357      *                   ValueLayout.JAVA_BYTE, 0, array.length)
358      *}
359      * @param elementLayout the element layout of the array to be allocated.
360      * @param elements      the byte elements to be copied to the newly allocated memory block.
361      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
362      */
363     @ForceInline
364     default MemorySegment allocateFrom(ValueLayout.OfByte elementLayout, byte... elements) {
365         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
366                 ValueLayout.JAVA_BYTE, 0, elements.length);
367     }
368 
369     /**
370      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
371      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code short} {@code elements} as
372      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
373      *
374      * @implSpec the default implementation for this method is equivalent to the following code:
375      * {@snippet lang = java:
376      * this.allocateFrom(layout, MemorySegment.ofArray(array),
377      *                   ValueLayout.JAVA_SHORT, 0, array.length)
378      *}
379      * @param elementLayout the element layout of the array to be allocated.
380      * @param elements      the short elements to be copied to the newly allocated memory block.
381      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
382      */
383     @ForceInline
384     default MemorySegment allocateFrom(ValueLayout.OfShort elementLayout, short... elements) {
385         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
386                 ValueLayout.JAVA_SHORT, 0, elements.length);
387     }
388 
389     /**
390      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
391      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code char} {@code elements} as
392      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
393      *
394      * @implSpec the default implementation for this method is equivalent to the following code:
395      * {@snippet lang = java:
396      * this.allocateFrom(layout, MemorySegment.ofArray(array),
397      *                   ValueLayout.JAVA_CHAR, 0, array.length)
398      *}
399      * @param elementLayout the element layout of the array to be allocated.
400      * @param elements      the char elements to be copied to the newly allocated memory block.
401      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
402      */
403     @ForceInline
404     default MemorySegment allocateFrom(ValueLayout.OfChar elementLayout, char... elements) {
405         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
406                 ValueLayout.JAVA_CHAR, 0, elements.length);
407     }
408 
409     /**
410      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
411      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code int} {@code elements} as
412      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
413      *
414      * @implSpec the default implementation for this method is equivalent to the following code:
415      * {@snippet lang = java:
416      * this.allocateFrom(layout, MemorySegment.ofArray(array),
417      *                   ValueLayout.JAVA_INT, 0, array.length)
418      *}
419      * @param elementLayout the element layout of the array to be allocated.
420      * @param elements      the int elements to be copied to the newly allocated memory block.
421      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
422      */
423     @ForceInline
424     default MemorySegment allocateFrom(ValueLayout.OfInt elementLayout, int... elements) {
425         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
426                 ValueLayout.JAVA_INT, 0, elements.length);
427     }
428 
429     /**
430      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
431      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code float} {@code elements} as
432      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
433      *
434      * @implSpec the default implementation for this method is equivalent to the following code:
435      * {@snippet lang = java:
436      * this.allocateFrom(layout, MemorySegment.ofArray(array),
437      *                   ValueLayout.JAVA_FLOAT, 0, array.length)
438      *}
439      * @param elementLayout the element layout of the array to be allocated.
440      * @param elements the float elements to be copied to the newly allocated memory block.
441      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
442      */
443     @ForceInline
444     default MemorySegment allocateFrom(ValueLayout.OfFloat elementLayout, float... elements) {
445         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
446                 ValueLayout.JAVA_FLOAT, 0, elements.length);
447     }
448 
449     /**
450      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
451      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code long} {@code elements} as
452      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
453      *
454      * @implSpec the default implementation for this method is equivalent to the following code:
455      * {@snippet lang = java:
456      * this.allocateFrom(layout, MemorySegment.ofArray(array),
457      *                   ValueLayout.JAVA_LONG, 0, array.length)
458      *}
459      * @param elementLayout the element layout of the array to be allocated.
460      * @param elements the long elements to be copied to the newly allocated memory block.
461      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
462      */
463     @ForceInline
464     default MemorySegment allocateFrom(ValueLayout.OfLong elementLayout, long... elements) {
465         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
466                 ValueLayout.JAVA_LONG, 0, elements.length);
467     }
468 
469     /**
470      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
471      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code double} {@code elements} as
472      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
473      *
474      * @implSpec the default implementation for this method is equivalent to the following code:
475      * {@snippet lang = java:
476      * this.allocateFrom(layout, MemorySegment.ofArray(array),
477      *                   ValueLayout.JAVA_DOUBLE, 0, array.length)
478      *}
479      * @param elementLayout the element layout of the array to be allocated.
480      * @param elements      the double elements to be copied to the newly allocated memory block.
481      * @throws IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}.
482      */
483     @ForceInline
484     default MemorySegment allocateFrom(ValueLayout.OfDouble elementLayout, double... elements) {
485         return allocateFrom(elementLayout, MemorySegment.ofArray(elements),
486                 ValueLayout.JAVA_DOUBLE, 0, elements.length);
487     }
488 
489     /**
490      * {@return a new memory segment with the given layout}
491      *
492      * @implSpec The default implementation for this method calls
493      * {@code this.allocate(layout.byteSize(), layout.byteAlignment())}.
494      *
495      * @param layout the layout of the block of memory to be allocated.
496      */
497     default MemorySegment allocate(MemoryLayout layout) {
498         Objects.requireNonNull(layout);
499         return allocate(layout.byteSize(), layout.byteAlignment());
500     }
501 
502     /**
503      * {@return a new memory segment with the given {@code elementLayout} and {@code count}}
504      *
505      * @implSpec The default implementation for this method calls
506      * {@code this.allocate(MemoryLayout.sequenceLayout(count, elementLayout))}.
507      *
508      * @param elementLayout the array element layout.
509      * @param count the array element count.
510      * @throws IllegalArgumentException if {@code elementLayout.byteSize() * count} overflows.
511      * @throws IllegalArgumentException if {@code count < 0}.
512      */
513     default MemorySegment allocate(MemoryLayout elementLayout, long count) {
514         Objects.requireNonNull(elementLayout);
515         if (count < 0) {
516             throw new IllegalArgumentException("Negative array size");
517         }
518         return allocate(MemoryLayout.sequenceLayout(count, elementLayout));
519     }
520 
521     /**
522      * {@return a new memory segment with the given {@code byteSize}}
523      *
524      * @implSpec The default implementation for this method calls
525      * {@code this.allocate(byteSize, 1)}.
526      *
527      * @param byteSize the size (in bytes) of the block of memory to be allocated.
528      * @throws IllegalArgumentException if {@code byteSize < 0}
529      */
530     default MemorySegment allocate(long byteSize) {
531         return allocate(byteSize, 1);
532     }
533 
534     /**
535      * {@return a new memory segment with the given {@code byteSize} and {@code byteAlignment}}
536      *
537      * @param byteSize the size (in bytes) of the block of memory to be allocated.
538      * @param byteAlignment the alignment (in bytes) of the block of memory to be allocated.
539      * @throws IllegalArgumentException if {@code byteSize < 0}, {@code byteAlignment <= 0},
540      * or if {@code byteAlignment} is not a power of 2.
541      */
542     MemorySegment allocate(long byteSize, long byteAlignment);
543 
544     /**
545      * Returns a segment allocator which responds to allocation requests by returning consecutive slices
546      * obtained from the provided segment. Each new allocation request will return a new slice starting at the
547      * current offset (modulo additional padding to satisfy alignment constraint), with given size.
548      * <p>
549      * The returned allocator throws {@link IndexOutOfBoundsException} when a slice of the provided
550      * segment with the requested size and alignment cannot be found.
551      *
552      * @implNote A slicing allocator is not <em>thread-safe</em>.
553      *
554      * @param segment the segment which the returned allocator should slice from.
555      * @return a new slicing allocator
556      */
557     static SegmentAllocator slicingAllocator(MemorySegment segment) {
558         Objects.requireNonNull(segment);
559         return new SlicingAllocator(segment);
560     }
561 
562     /**
563      * Returns a segment allocator which responds to allocation requests by recycling a single segment. Each
564      * new allocation request will return a new slice starting at the segment offset {@code 0}, hence the name
565      * <em>prefix allocator</em>.
566      * Equivalent to (but likely more efficient than) the following code:
567      * {@snippet lang=java :
568      * MemorySegment segment = ...
569      * SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size, align);
570      * }
571      * The returned allocator throws {@link IndexOutOfBoundsException} when a slice of the provided
572      * segment with the requested size and alignment cannot be found.
573      *
574      * @apiNote A prefix allocator can be useful to limit allocation requests in case a client
575      * knows that they have fully processed the contents of the allocated segment before the subsequent allocation request
576      * takes place.
577      * @implNote While a prefix allocator is <em>thread-safe</em>, concurrent access on the same recycling
578      * allocator might cause a thread to overwrite contents written to the underlying segment by a different thread.
579      *
580      * @param segment the memory segment to be recycled by the returned allocator.
581      * @return an allocator which recycles an existing segment upon each new allocation request.
582      */
583     static SegmentAllocator prefixAllocator(MemorySegment segment) {
584         return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment);
585     }
586 
587     @ForceInline
588     private MemorySegment allocateNoInit(long byteSize) {
589         return this instanceof ArenaImpl arenaImpl ?
590                 arenaImpl.allocateNoInit(byteSize, 1) :
591                 allocate(byteSize);
592     }
593 
594     @ForceInline
595     private MemorySegment allocateNoInit(MemoryLayout layout) {
596         return this instanceof ArenaImpl arenaImpl ?
597                 arenaImpl.allocateNoInit(layout.byteSize(), layout.byteAlignment()) :
598                 allocate(layout);
599     }
600 
601     @ForceInline
602     private MemorySegment allocateNoInit(MemoryLayout layout, long size) {
603         return this instanceof ArenaImpl arenaImpl ?
604                 arenaImpl.allocateNoInit(layout.byteSize() * size, layout.byteAlignment()) :
605                 allocate(layout, size);
606     }
607 }