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.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 
476     /**
477      * {@return a new memory segment with the given {@code byteSize} and {@code byteAlignment}}
478      *
479      * @param byteSize the size (in bytes) of the block of memory to be allocated.
480      * @param byteAlignment the alignment (in bytes) of the block of memory to be allocated.
481      * @throws IllegalArgumentException if {@code byteSize < 0}, {@code byteAlignment <= 0},
482      * or if {@code byteAlignment} is not a power of 2.
483      */
484     MemorySegment allocate(long byteSize, long byteAlignment);
485 
486     /**
487      * Returns a segment allocator which responds to allocation requests by returning consecutive slices
488      * obtained from the provided segment. Each new allocation request will return a new slice starting at the
489      * current offset (modulo additional padding to satisfy alignment constraint), with given size.
490      * <p>
491      * The returned allocator throws {@link IndexOutOfBoundsException} when a slice of the provided
492      * segment with the requested size and alignment cannot be found.
493      *
494      * @implNote A slicing allocator is not <em>thread-safe</em>.
495      *
496      * @param segment the segment which the returned allocator should slice from.
497      * @return a new slicing allocator
498      */
499     static SegmentAllocator slicingAllocator(MemorySegment segment) {
500         Objects.requireNonNull(segment);
501         return new SlicingAllocator(segment);
502     }
503 
504     /**
505      * Returns a segment allocator which responds to allocation requests by recycling a single segment. Each
506      * new allocation request will return a new slice starting at the segment offset {@code 0}, hence the name
507      * <em>prefix allocator</em>.
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 }