< prev index next >

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

Print this page

  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.lang.invoke.VarHandle;
 29 import java.lang.reflect.Array;
 30 import java.nio.ByteOrder;

 31 import java.nio.charset.StandardCharsets;
 32 import java.util.Objects;
 33 import java.util.function.Function;
 34 import jdk.internal.foreign.AbstractMemorySegmentImpl;

 35 import jdk.internal.foreign.SlicingAllocator;
 36 import jdk.internal.foreign.Utils;
 37 import jdk.internal.javac.PreviewFeature;
 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 19
 74  */
 75 @FunctionalInterface
 76 @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
 77 public interface SegmentAllocator {
 78 
 79     /**
 80      * {@return a new memory segment with a Java string converted into a UTF-8 encoded, null-terminated C string}



















 81      * <p>
 82      * This method always replaces malformed-input and unmappable-character
 83      * sequences with this charset's default replacement byte array.  The
 84      * {@link java.nio.charset.CharsetEncoder} class should be used when more
 85      * control over the encoding process is required.
 86      * <p>
 87      * If the given string contains any {@code '\0'} characters, they will be
 88      * copied as well. This means that, depending on the method used to read
 89      * the string, such as {@link MemorySegment#getUtf8String(long)}, the string
 90      * will appear truncated when read again.
 91      *




 92      * @implSpec The default implementation for this method copies the contents of the provided Java string
 93      * into a new memory segment obtained by calling {@code this.allocate(str.length() + 1)}.
 94      * @param str the Java string to be converted into a C string.





 95      */
 96     default MemorySegment allocateUtf8String(String str) {


 97         Objects.requireNonNull(str);
 98         return Utils.toCString(str.getBytes(StandardCharsets.UTF_8), this);







 99     }
100 
101     /**
102      * {@return a new memory segment initialized with the provided {@code byte} {@code value} as
103      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
104      *
105      * @implSpec The default implementation is equivalent to:
106      * {@snippet lang=java :
107      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
108      *  seg.set(layout, 0, value);
109      *  return seg;
110      * }
111      *
112      * @param layout the layout of the block of memory to be allocated.
113      * @param value  the value to be set in the newly allocated memory segment.
114      */
115     default MemorySegment allocate(ValueLayout.OfByte layout, byte value) {
116         Objects.requireNonNull(layout);
117         VarHandle handle = layout.varHandle();
118         MemorySegment seg = allocate(layout);
119         handle.set(seg, value);
120         return seg;
121     }
122 
123     /**
124      * {@return a new memory segment initialized with the provided {@code char} {@code value} as
125      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
126      *
127      * @implSpec The default implementation is equivalent to:
128      * {@snippet lang=java :
129      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
130      *  seg.set(layout, 0, value);
131      *  return seg;
132      * }
133      *
134      * @param layout the layout of the block of memory to be allocated.
135      * @param value  the value to be set in the newly allocated memory segment.
136      */
137     default MemorySegment allocate(ValueLayout.OfChar layout, char value) {
138         Objects.requireNonNull(layout);
139         VarHandle handle = layout.varHandle();
140         MemorySegment seg = allocate(layout);
141         handle.set(seg, value);
142         return seg;
143     }
144 
145     /**
146      * {@return a new memory segment initialized with the provided {@code short} {@code value} as
147      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
148      *
149      * @implSpec The default implementation is equivalent to:
150      * {@snippet lang=java :
151      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
152      *  seg.set(layout, 0, value);
153      *  return seg;
154      * }
155      *
156      * @param layout the layout of the block of memory to be allocated.
157      * @param value  the value to be set in the newly allocated memory segment.
158      */
159     default MemorySegment allocate(ValueLayout.OfShort layout, short value) {
160         Objects.requireNonNull(layout);
161         VarHandle handle = layout.varHandle();
162         MemorySegment seg = allocate(layout);
163         handle.set(seg, value);
164         return seg;
165     }
166 
167     /**
168      * {@return a new memory segment initialized with the provided {@code int} {@code value} as
169      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
170      *
171      * @implSpec The default implementation is equivalent to:
172      * {@snippet lang=java :
173      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
174      *  seg.set(layout, 0, value);
175      *  return seg;
176      * }
177      *
178      * @param layout the layout of the block of memory to be allocated.
179      * @param value  the value to be set in the newly allocated memory segment.
180      */
181     default MemorySegment allocate(ValueLayout.OfInt layout, int value) {
182         Objects.requireNonNull(layout);
183         VarHandle handle = layout.varHandle();
184         MemorySegment seg = allocate(layout);
185         handle.set(seg, value);
186         return seg;
187     }
188 
189     /**
190      * {@return a new memory segment initialized with the provided {@code float} {@code value} as
191      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
192      *
193      * @implSpec The default implementation is equivalent to:
194      * {@snippet lang=java :
195      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
196      *  seg.set(layout, 0, value);
197      *  return seg;
198      * }
199      *
200      * @param layout the layout of the block of memory to be allocated.
201      * @param value  the value to be set in the newly allocated memory segment.
202      */
203     default MemorySegment allocate(ValueLayout.OfFloat layout, float value) {
204         Objects.requireNonNull(layout);
205         VarHandle handle = layout.varHandle();
206         MemorySegment seg = allocate(layout);
207         handle.set(seg, value);
208         return seg;
209     }
210 
211     /**
212      * {@return a new memory segment initialized with the provided {@code long} {@code value} as
213      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
214      *
215      * @implSpec The default implementation is equivalent to:
216      * {@snippet lang=java :
217      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
218      *  seg.set(layout, 0, value);
219      *  return seg;
220      * }
221      *
222      * @param layout the layout of the block of memory to be allocated.
223      * @param value  the value to be set in the newly allocated memory segment.
224      */
225     default MemorySegment allocate(ValueLayout.OfLong layout, long value) {
226         Objects.requireNonNull(layout);
227         VarHandle handle = layout.varHandle();
228         MemorySegment seg = allocate(layout);
229         handle.set(seg, value);
230         return seg;
231     }
232 
233     /**
234      * {@return a new memory segment initialized with the provided {@code double} {@code value} as
235      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
236      *
237      * @implSpec The default implementation is equivalent to:
238      * {@snippet lang=java :
239      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
240      *  seg.set(layout, 0, value);
241      *  return seg;
242      * }
243      *
244      * @param layout the layout of the block of memory to be allocated.
245      * @param value  the value to be set in the newly allocated memory segment.
246      */
247     default MemorySegment allocate(ValueLayout.OfDouble layout, double value) {
248         Objects.requireNonNull(layout);
249         VarHandle handle = layout.varHandle();
250         MemorySegment seg = allocate(layout);
251         handle.set(seg, value);
252         return seg;
253     }
254 
255     /**
256      * {@return a new memory segment initialized with the address of the provided {@code value} as
257      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
258      * <p>
259      * The address value might be narrowed according to the platform address size (see {@link ValueLayout#ADDRESS}).
260      *
261      * @implSpec The default implementation is equivalent to:
262      * {@snippet lang=java :
263      *  Objects.requireNonNull(value);
264      *  MemorySegment seg = allocate(Objects.requireNonNull(layout));
265      *  seg.set(layout, 0, value);
266      *  return seg;
267      * }
268      *
269      * @param layout the layout of the block of memory to be allocated.
270      * @param value  the value to be set in the newly allocated memory segment.
271      */
272     default MemorySegment allocate(AddressLayout layout, MemorySegment value) {
273         Objects.requireNonNull(value);
274         Objects.requireNonNull(layout);
275         MemorySegment seg = allocate(layout);
276         layout.varHandle().set(seg, value);
277         return seg;








































278     }
279 
280     /**
281      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
282      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code byte} {@code elements} as
283      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
284      *
285      * @implSpec The default implementation is equivalent to:
286      * {@snippet lang=java :
287      *  int size = Objects.requireNonNull(elements).length;
288      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
289      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
290      *  return seg;
291      * }
292      *
293      * @param elementLayout the element layout of the array to be allocated.
294      * @param elements      the short elements to be copied to the newly allocated memory block.

295      */
296     default MemorySegment allocateArray(ValueLayout.OfByte elementLayout, byte... elements) {
297         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);


298     }
299 
300     /**
301      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
302      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code short} {@code elements} as
303      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
304      *
305      * @implSpec The default implementation is equivalent to:
306      * {@snippet lang=java :
307      *  int size = Objects.requireNonNull(elements).length;
308      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
309      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
310      *  return seg;
311      * }
312      *
313      * @param elementLayout the element layout of the array to be allocated.
314      * @param elements      the short elements to be copied to the newly allocated memory block.

315      */
316     default MemorySegment allocateArray(ValueLayout.OfShort elementLayout, short... elements) {
317         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);


318     }
319 
320     /**
321      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
322      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code char} {@code elements} as
323      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
324      *
325      * @implSpec The default implementation is equivalent to:
326      * {@snippet lang=java :
327      *  int size = Objects.requireNonNull(elements).length;
328      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
329      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
330      *  return seg;
331      * }
332      *
333      * @param elementLayout the element layout of the array to be allocated.
334      * @param elements      the short elements to be copied to the newly allocated memory block.

335      */
336     default MemorySegment allocateArray(ValueLayout.OfChar elementLayout, char... elements) {
337         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);


338     }
339 
340     /**
341      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
342      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code int} {@code elements} as
343      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
344      *
345      * @implSpec The default implementation is equivalent to:
346      * {@snippet lang=java :
347      *  int size = Objects.requireNonNull(elements).length;
348      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
349      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
350      *  return seg;
351      * }
352      *
353      * @param elementLayout the element layout of the array to be allocated.
354      * @param elements      the short elements to be copied to the newly allocated memory block.

355      */
356     default MemorySegment allocateArray(ValueLayout.OfInt elementLayout, int... elements) {
357         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);


358     }
359 
360     /**
361      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
362      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code float} {@code elements} as
363      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
364      *
365      * @implSpec The default implementation is equivalent to:
366      * {@snippet lang=java :
367      *  int size = Objects.requireNonNull(elements).length;
368      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
369      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
370      *  return seg;
371      * }
372      *
373      * @param elementLayout the element layout of the array to be allocated.
374      * @param elements      the short elements to be copied to the newly allocated memory block.

375      */
376     default MemorySegment allocateArray(ValueLayout.OfFloat elementLayout, float... elements) {
377         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);


378     }
379 
380     /**
381      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
382      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code long} {@code elements} as
383      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
384      *
385      * @implSpec The default implementation is equivalent to:
386      * {@snippet lang=java :
387      *  int size = Objects.requireNonNull(elements).length;
388      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
389      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
390      *  return seg;
391      * }
392      *
393      * @param elementLayout the element layout of the array to be allocated.
394      * @param elements      the short elements to be copied to the newly allocated memory block.

395      */
396     default MemorySegment allocateArray(ValueLayout.OfLong elementLayout, long... elements) {
397         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);


398     }
399 
400     /**
401      * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of
402      * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code double} {@code elements} as
403      * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)}
404      *
405      * @implSpec The default implementation is equivalent to:
406      * {@snippet lang=java :
407      *  int size = Objects.requireNonNull(elements).length;
408      *  MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
409      *  MemorySegment.copy(elements, 0, seg, elementLayout, 0, size);
410      *  return seg;
411      * }
412      *
413      * @param elementLayout the element layout of the array to be allocated.
414      * @param elements      the short elements to be copied to the newly allocated memory block.

415      */
416     default MemorySegment allocateArray(ValueLayout.OfDouble elementLayout, double... elements) {
417         return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray);
418     }
419 
420     private <Z> MemorySegment copyArrayWithSwapIfNeeded(Z array, ValueLayout elementLayout,
421                                                         Function<Z, MemorySegment> heapSegmentFactory) {
422         int size = Array.getLength(Objects.requireNonNull(array));
423         MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size);
424         if (size > 0) {
425             MemorySegment.copy(heapSegmentFactory.apply(array), elementLayout, 0,
426                     seg, elementLayout.withOrder(ByteOrder.nativeOrder()), 0, size);
427         }
428         return seg;
429     }
430 
431     /**
432      * {@return a new memory segment with the given layout}
433      *
434      * @implSpec The default implementation for this method calls
435      * {@code this.allocate(layout.byteSize(), layout.byteAlignment())}.
436      *
437      * @param layout the layout of the block of memory to be allocated.
438      */
439     default MemorySegment allocate(MemoryLayout layout) {
440         Objects.requireNonNull(layout);
441         return allocate(layout.byteSize(), layout.byteAlignment());
442     }
443 
444     /**
445      * {@return a new memory segment with the given {@code elementLayout} and {@code count}}
446      *
447      * @implSpec The default implementation for this method calls
448      * {@code this.allocate(MemoryLayout.sequenceLayout(count, elementLayout))}.
449      *
450      * @param elementLayout the array element layout.
451      * @param count the array element count.
452      * @throws IllegalArgumentException if {@code elementLayout.byteSize() * count} overflows.
453      * @throws IllegalArgumentException if {@code count < 0}.
454      */
455     default MemorySegment allocateArray(MemoryLayout elementLayout, long count) {
456         Objects.requireNonNull(elementLayout);
457         if (count < 0) {
458             throw new IllegalArgumentException("Negative array size");
459         }
460         return allocate(MemoryLayout.sequenceLayout(count, elementLayout));
461     }
462 
463     /**
464      * {@return a new memory segment with the given {@code byteSize}}
465      *
466      * @implSpec The default implementation for this method calls
467      * {@code this.allocate(byteSize, 1)}.
468      *
469      * @param byteSize the size (in bytes) of the block of memory to be allocated.
470      * @throws IllegalArgumentException if {@code byteSize < 0}
471      */
472     default MemorySegment allocate(long byteSize) {
473         return allocate(byteSize, 1);
474     }
475 

508      * Equivalent to (but likely more efficient than) the following code:
509      * {@snippet lang=java :
510      * MemorySegment segment = ...
511      * SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size, align);
512      * }
513      * The returned allocator throws {@link IndexOutOfBoundsException} when a slice of the provided
514      * segment with the requested size and alignment cannot be found.
515      *
516      * @apiNote A prefix allocator can be useful to limit allocation requests in case a client
517      * knows that they have fully processed the contents of the allocated segment before the subsequent allocation request
518      * takes place.
519      * @implNote While a prefix allocator is <em>thread-safe</em>, concurrent access on the same recycling
520      * allocator might cause a thread to overwrite contents written to the underlying segment by a different thread.
521      *
522      * @param segment the memory segment to be recycled by the returned allocator.
523      * @return an allocator which recycles an existing segment upon each new allocation request.
524      */
525     static SegmentAllocator prefixAllocator(MemorySegment segment) {
526         return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment);
527     }





















528 }

  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 

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 }
< prev index next >