< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/CLinker.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 jdk.incubator.foreign;
 27 
 28 import jdk.internal.foreign.AbstractCLinker;
 29 import jdk.internal.foreign.NativeMemorySegmentImpl;
 30 import jdk.internal.foreign.PlatformLayouts;
 31 import jdk.internal.foreign.SystemLookup;
 32 import jdk.internal.foreign.abi.SharedUtils;
 33 import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64VaList;
 34 import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64VaList;
 35 import jdk.internal.foreign.abi.x64.sysv.SysVVaList;
 36 import jdk.internal.foreign.abi.x64.windows.WinVaList;
 37 import jdk.internal.reflect.CallerSensitive;
 38 import jdk.internal.reflect.Reflection;
 39 
 40 import java.lang.constant.Constable;
 41 import java.lang.invoke.MethodHandle;
 42 import java.lang.invoke.MethodType;
 43 import java.nio.charset.Charset;
 44 import java.nio.charset.StandardCharsets;
 45 import java.util.Objects;
 46 import java.util.function.Consumer;
 47 
 48 import static jdk.internal.foreign.PlatformLayouts.*;
 49 
 50 /**
 51  * A C linker implements the C Application Binary Interface (ABI) calling conventions.
 52  * Instances of this interface can be used to link foreign functions in native libraries that
 53  * follow the JVM's target platform C ABI.
 54  * <p>
 55  * Linking a foreign function is a process which requires two components: a method type, and
 56  * a function descriptor. The method type, consists of a set of <em>carrier</em> types, which, together,
 57  * specify the Java signature which clients must adhere to when calling the underlying foreign function.
 58  * The function descriptor contains a set of memory layouts which, together, specify the foreign function
 59  * signature and classification information (via a custom layout attributes, see {@link TypeKind}), so that linking can take place.
 60  * <p>
 61  * Clients of this API can build function descriptors using the predefined memory layout constants
 62  * (based on a subset of the built-in types provided by the C language), found in this interface; alternatively,
 63  * they can also decorate existing value layouts using the required {@link TypeKind} classification attribute
 64  * (this can be done using the {@link MemoryLayout#withAttribute(String, Constable)} method). A failure to do so might
 65  * result in linkage errors, given that linking requires additional classification information to determine, for instance,
 66  * how arguments should be loaded into registers during a foreign function call.
 67  * <p>
 68  * Implementations of this interface support the following primitive carrier types:
 69  * {@code byte}, {@code short}, {@code char}, {@code int}, {@code long}, {@code float},
 70  * and {@code double}, as well as {@link MemoryAddress} for passing pointers, and
 71  * {@link MemorySegment} for passing structs and unions. Finally, the {@link VaList}
 72  * carrier type can be used to match the native {@code va_list} type.
 73  * <p>
 74  * For the linking process to be successful, some requirements must be satisfied; if {@code M} and {@code F} are
 75  * the method type (obtained after dropping any prefix arguments) and the function descriptor, respectively,
 76  * used during the linking process, then it must be that:



 77  * <ul>
 78  *     <li>The arity of {@code M} is the same as that of {@code F};</li>
 79  *     <li>If the return type of {@code M} is {@code void}, then {@code F} should have no return layout
 80  *     (see {@link FunctionDescriptor#ofVoid(MemoryLayout...)});</li>
 81  *     <li>for each pair of carrier type {@code C} and layout {@code L} in {@code M} and {@code F}, respectively,
 82  *     where {@code C} and {@code L} refer to the same argument, or to the return value, the following conditions must hold:
 83  *     <ul>
 84  *       <li>If {@code C} is a primitve type, then {@code L} must be a {@code ValueLayout}, and the size of the layout must match
 85  *       that of the carrier type (see {@link Integer#SIZE} and similar fields in other primitive wrapper classes);</li>
 86  *       <li>If {@code C} is {@code MemoryAddress.class}, then {@code L} must be a {@code ValueLayout}, and its size must match
 87  *       the platform's address size (see {@link MemoryLayouts#ADDRESS}). For this purpose, the {@link CLinker#C_POINTER} layout
 88  *       constant can  be used;</li>
 89  *       <li>If {@code C} is {@code MemorySegment.class}, then {@code L} must be a {@code GroupLayout}</li>
 90  *       <li>If {@code C} is {@code VaList.class}, then {@code L} must be {@link CLinker#C_VA_LIST}</li>
 91  *     </ul>
 92  *     </li>
 93  * </ul>
 94  *













 95  * <p>Variadic functions, declared in C either with a trailing ellipses ({@code ...}) at the end of the formal parameter
 96  * list or with an empty formal parameter list, are not supported directly. It is not possible to create a method handle
 97  * that takes a variable number of arguments, and neither is it possible to create an upcall stub wrapping a method
 98  * handle that accepts a variable number of arguments. However, for downcalls only, it is possible to link a native
 99  * variadic function by using a <em>specialized</em> method type and function descriptor: for each argument that is to be
100  * passed as a variadic argument, an explicit, additional, carrier type and memory layout must be present in the method type and
101  * function descriptor objects passed to the linker. Furthermore, as memory layouts corresponding to variadic arguments in
102  * a function descriptor must contain additional classification information, it is required that
103  * {@link #asVarArg(MemoryLayout)} is used to create the memory layouts for each parameter corresponding to a variadic
104  * argument in a specialized function descriptor.
105  *
106  * <p>On unsupported platforms this class will fail to initialize with an {@link ExceptionInInitializerError}.
107  *
108  * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
109  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>























110  *
111  * @implSpec
112  * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
113  */
114 public sealed interface CLinker permits AbstractCLinker {
115 
116     /**
117      * Returns the C linker for the current platform.
118      * <p>
119      * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
120      * Restricted methods are unsafe, and, if used incorrectly, their use might crash
121      * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
122      * restricted methods, and use safe and supported functionalities, where possible.
123      *
124      * @return a linker for this system.
125      * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
126      * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
127      * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
128      */
129     @CallerSensitive
130     static CLinker getInstance() {
131         Reflection.ensureNativeAccess(Reflection.getCallerClass());
132         return SharedUtils.getSystemLinker();
133     }
134 
135     /**
136      * Obtains a system lookup which is suitable to find symbols in the standard C libraries. The set of symbols
137      * available for lookup is unspecified, as it depends on the platform and on the operating system.
138      * <p>
139      * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
140      * Restricted methods are unsafe, and, if used incorrectly, their use might crash
141      * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
142      * restricted methods, and use safe and supported functionalities, where possible.
143      * @return a system-specific library lookup which is suitable to find symbols in the standard C libraries.
144      * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
145      * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
146      * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
147      */
148     @CallerSensitive
149     static SymbolLookup systemLookup() {
150         Reflection.ensureNativeAccess(Reflection.getCallerClass());
151         return SystemLookup.getInstance();
152     }
153 
154     /**
155      * Obtains a foreign method handle, with the given type and featuring the given function descriptor,
156      * which can be used to call a target foreign function at the given address.
157      * <p>
158      * If the provided method type's return type is {@code MemorySegment}, then the resulting method handle features
159      * an additional prefix parameter, of type {@link SegmentAllocator}, which will be used by the linker runtime
160      * to allocate structs returned by-value.





161      *
162      * @param symbol   downcall symbol.
163      * @param type     the method type.
164      * @param function the function descriptor.
165      * @return the downcall method handle.
166      * @throws IllegalArgumentException in the case of a method type and function descriptor mismatch, or if the symbol
167      *                                  is {@link MemoryAddress#NULL}
168      *
169      * @see SymbolLookup
170      */
171     MethodHandle downcallHandle(Addressable symbol, MethodType type, FunctionDescriptor function);
172 
173     /**
174      * Obtain a foreign method handle, with the given type and featuring the given function descriptor,
175      * which can be used to call a target foreign function at the given address.
176      * <p>
177      * If the provided method type's return type is {@code MemorySegment}, then the provided allocator will be used by
178      * the linker runtime to allocate structs returned by-value.
179      *
180      * @param symbol    downcall symbol.
181      * @param allocator the segment allocator.
182      * @param type      the method type.
183      * @param function  the function descriptor.
184      * @return the downcall method handle.
185      * @throws IllegalArgumentException in the case of a method type and function descriptor mismatch, or if the symbol
186      *                                  is {@link MemoryAddress#NULL}
187      *
188      * @see SymbolLookup
189      */
190     MethodHandle downcallHandle(Addressable symbol, SegmentAllocator allocator, MethodType type, FunctionDescriptor function);



191 
192     /**
193      * Obtains a foreign method handle, with the given type and featuring the given function descriptor, which can be
194      * used to call a target foreign function at an address.
195      * The resulting method handle features a prefix parameter (as the first parameter) corresponding to the address, of
196      * type {@link Addressable}.
197      * <p>
198      * If the provided method type's return type is {@code MemorySegment}, then the resulting method handle features an
199      * additional prefix parameter (inserted immediately after the address parameter), of type {@link SegmentAllocator}),
200      * which will be used by the linker runtime to allocate structs returned by-value.
201      * <p>
202      * The returned method handle will throw an {@link IllegalArgumentException} if the target address passed to it is
203      * {@link MemoryAddress#NULL}, or a {@link NullPointerException} if the target address is {@code null}.
204      *
205      * @param type     the method type.
206      * @param function the function descriptor.
207      * @return the downcall method handle.
208      * @throws IllegalArgumentException in the case of a method type and function descriptor mismatch.

209      *
210      * @see SymbolLookup
211      */
212     MethodHandle downcallHandle(MethodType type, FunctionDescriptor function);
213 
214     /**
215      * Allocates a native stub with given scope which can be passed to other foreign functions (as a function pointer);
216      * calling such a function pointer from native code will result in the execution of the provided method handle.
217      *
218      * <p>
219      * The returned memory address is associated with the provided scope. When such scope is closed,
220      * the corresponding native stub will be deallocated.
221      * <p>
222      * The target method handle should not throw any exceptions. If the target method handle does throw an exception,
223      * the VM will exit with a non-zero exit code. To avoid the VM aborting due to an uncaught exception, clients
224      * could wrap all code in the target method handle in a try/catch block that catches any {@link Throwable}, for
225      * instance by using the {@link java.lang.invoke.MethodHandles#catchException(MethodHandle, Class, MethodHandle)}
226      * method handle combinator, and handle exceptions as desired in the corresponding catch block.
227      *
228      * @param target   the target method handle.
229      * @param function the function descriptor.
230      * @param scope the upcall stub scope.
231      * @return the native stub segment.
232      * @throws IllegalArgumentException if the target's method type and the function descriptor mismatch.
233      * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
234      * than the thread owning {@code scope}.
235      */
236     MemoryAddress upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope);
237 
238     /**
239      * The layout for the {@code char} C type
240      */
241     ValueLayout C_CHAR = pick(SysV.C_CHAR, Win64.C_CHAR, AArch64.C_CHAR);
242     /**
243      * The layout for the {@code short} C type
244      */
245     ValueLayout C_SHORT = pick(SysV.C_SHORT, Win64.C_SHORT, AArch64.C_SHORT);
246     /**
247      * The layout for the {@code int} C type
248      */
249     ValueLayout C_INT = pick(SysV.C_INT, Win64.C_INT, AArch64.C_INT);
250     /**
251      * The layout for the {@code long} C type
252      */
253     ValueLayout C_LONG = pick(SysV.C_LONG, Win64.C_LONG, AArch64.C_LONG);
254     /**
255      * The layout for the {@code long long} C type.
256      */
257     ValueLayout C_LONG_LONG = pick(SysV.C_LONG_LONG, Win64.C_LONG_LONG, AArch64.C_LONG_LONG);
258     /**
259      * The layout for the {@code float} C type
260      */
261     ValueLayout C_FLOAT = pick(SysV.C_FLOAT, Win64.C_FLOAT, AArch64.C_FLOAT);
262     /**
263      * The layout for the {@code double} C type
264      */
265     ValueLayout C_DOUBLE = pick(SysV.C_DOUBLE, Win64.C_DOUBLE, AArch64.C_DOUBLE);
266     /**
267      * The {@code T*} native type.
268      */
269     ValueLayout C_POINTER = pick(SysV.C_POINTER, Win64.C_POINTER, AArch64.C_POINTER);
270     /**
271      * The layout for the {@code va_list} C type
272      */
273     MemoryLayout C_VA_LIST = pick(SysV.C_VA_LIST, Win64.C_VA_LIST, AArch64.C_VA_LIST);
274 
275     /**
276      * Returns a memory layout that is suitable to use as the layout for variadic arguments in a specialized
277      * function descriptor.
278      * @param <T> the memory layout type
279      * @param layout the layout the adapt
280      * @return a potentially newly created layout with the right attributes
281      */
282     @SuppressWarnings("unchecked")
283     static <T extends MemoryLayout> T asVarArg(T layout) {
284         Objects.requireNonNull(layout);
285         return (T) PlatformLayouts.asVarArg(layout);
286     }
287 
288     /**
289      * Converts a Java string into a UTF-8 encoded, null-terminated C string,
290      * storing the result into a native memory segment allocated using the provided allocator.
291      * <p>
292      * This method always replaces malformed-input and unmappable-character
293      * sequences with this charset's default replacement byte array.  The
294      * {@link java.nio.charset.CharsetEncoder} class should be used when more
295      * control over the encoding process is required.
296      *
297      * @param str the Java string to be converted into a C string.
298      * @param allocator the allocator to be used for the native segment allocation.
299      * @return a new native memory segment containing the converted C string.
300      */
301     static MemorySegment toCString(String str, SegmentAllocator allocator) {
302         Objects.requireNonNull(str);
303         Objects.requireNonNull(allocator);
304         return toCString(str.getBytes(StandardCharsets.UTF_8), allocator);
305     }
306 
307     /**
308      * Converts a Java string into a UTF-8 encoded, null-terminated C string,
309      * storing the result into a native memory segment associated with the provided resource scope.
310      * <p>
311      * This method always replaces malformed-input and unmappable-character
312      * sequences with this charset's default replacement byte array.  The
313      * {@link java.nio.charset.CharsetEncoder} class should be used when more
314      * control over the encoding process is required.
315      *
316      * @param str the Java string to be converted into a C string.
317      * @param scope the resource scope to be associated with the returned segment.
318      * @return a new native memory segment containing the converted C string.
319      * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
320      * than the thread owning {@code scope}.
321      */
322     static MemorySegment toCString(String str, ResourceScope scope) {
323         return toCString(str, SegmentAllocator.ofScope(scope));
324     }
325 
326     /**
327      * Converts a UTF-8 encoded, null-terminated C string stored at given address into a Java string.
328      * <p>
329      * This method always replaces malformed-input and unmappable-character
330      * sequences with this charset's default replacement string.  The {@link
331      * java.nio.charset.CharsetDecoder} class should be used when more control
332      * over the decoding process is required.
333      * <p>
334      * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
335      * Restricted methods are unsafe, and, if used incorrectly, their use might crash
336      * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
337      * restricted methods, and use safe and supported functionalities, where possible.
338      *
339      * @param addr the address at which the string is stored.
340      * @return a Java string with the contents of the null-terminated C string at given address.
341      * @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform,
342      * or if {@code addr == MemoryAddress.NULL}.
343      * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
344      * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
345      * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
346      */
347     @CallerSensitive
348     static String toJavaString(MemoryAddress addr) {
349         Reflection.ensureNativeAccess(Reflection.getCallerClass());
350         SharedUtils.checkAddress(addr);
351         return SharedUtils.toJavaStringInternal(NativeMemorySegmentImpl.EVERYTHING, addr.toRawLongValue());
352     }
353 
354     /**
355      * Converts a UTF-8 encoded, null-terminated C string stored at given address into a Java string.
356      * <p>
357      * This method always replaces malformed-input and unmappable-character
358      * sequences with this charset's default replacement string.  The {@link
359      * java.nio.charset.CharsetDecoder} class should be used when more control
360      * over the decoding process is required.
361      * @param addr the address at which the string is stored.
362      * @return a Java string with the contents of the null-terminated C string at given address.
363      * @throws IllegalArgumentException if the size of the native string is greater than the largest string supported by the platform.
364      * @throws IllegalStateException if the size of the native string is greater than the size of the segment
365      * associated with {@code addr}, or if {@code addr} is associated with a segment that is <em>not alive</em>.
366      */
367     static String toJavaString(MemorySegment addr) {
368         Objects.requireNonNull(addr);
369         return SharedUtils.toJavaStringInternal(addr, 0L);
370     }
371 
372     private static void copy(MemorySegment addr, byte[] bytes) {
373         var heapSegment = MemorySegment.ofArray(bytes);
374         addr.copyFrom(heapSegment);
375         MemoryAccess.setByteAtOffset(addr, bytes.length, (byte)0);
376     }
377 
378     private static MemorySegment toCString(byte[] bytes, SegmentAllocator allocator) {
379         MemorySegment addr = allocator.allocate(bytes.length + 1, 1L);
380         copy(addr, bytes);
381         return addr;
382     }
383 
384     /**
385      * Allocates memory of given size using malloc.
386      * <p>
387      * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
388      * Restricted methods are unsafe, and, if used incorrectly, their use might crash
389      * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
390      * restricted methods, and use safe and supported functionalities, where possible.
391      *
392      * @param size memory size to be allocated
393      * @return addr memory address of the allocated memory
394      * @throws OutOfMemoryError if malloc could not allocate the required amount of native memory.
395      * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
396      * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
397      * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
398      */
399     @CallerSensitive
400     static MemoryAddress allocateMemory(long size) {
401         Reflection.ensureNativeAccess(Reflection.getCallerClass());
402         MemoryAddress addr = SharedUtils.allocateMemoryInternal(size);
403         if (addr.equals(MemoryAddress.NULL)) {
404             throw new OutOfMemoryError();
405         } else {
406             return addr;
407         }
408     }
409 
410     /**
411      * Frees the memory pointed by the given memory address.
412      * <p>
413      * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
414      * Restricted methods are unsafe, and, if used incorrectly, their use might crash
415      * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
416      * restricted methods, and use safe and supported functionalities, where possible.
417      *
418      * @param addr memory address of the native memory to be freed
419      * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
420      * @throws IllegalArgumentException if {@code addr == MemoryAddress.NULL}.
421      * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
422      * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
423      */
424     @CallerSensitive
425     static void freeMemory(MemoryAddress addr) {
426         Reflection.ensureNativeAccess(Reflection.getCallerClass());
427         SharedUtils.checkAddress(addr);
428         SharedUtils.freeMemoryInternal(addr);
429     }
430 
431     /**
432      * An interface that models a C {@code va_list}.
433      * <p>
434      * A va list is a stateful cursor used to iterate over a set of variadic arguments.
435      * <p>
436      * Per the C specification (see C standard 6.5.2.2 Function calls - item 6),
437      * arguments to variadic calls are erased by way of 'default argument promotions',
438      * which erases integral types by way of integer promotion (see C standard 6.3.1.1 - item 2),
439      * and which erases all {@code float} arguments to {@code double}.
440      * <p>
441      * As such, this interface only supports reading {@code int}, {@code double},
442      * and any other type that fits into a {@code long}.
443      *
444      * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
445      * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
446      */
447     sealed interface VaList extends Addressable permits WinVaList, SysVVaList, LinuxAArch64VaList, MacOsAArch64VaList, SharedUtils.EmptyVaList {
448 
449         /**
450          * Reads the next value as an {@code int} and advances this va list's position.
451          *
452          * @param layout the layout of the value
453          * @return the value read as an {@code int}
454          * @throws IllegalStateException if the resource scope associated with this instance has been closed
455          * (see {@link #scope()}).
456          * @throws IllegalArgumentException if the given memory layout is not compatible with {@code int}
457          */
458         int vargAsInt(MemoryLayout layout);
459 
460         /**
461          * Reads the next value as a {@code long} and advances this va list's position.
462          *
463          * @param layout the layout of the value
464          * @return the value read as an {@code long}
465          * @throws IllegalStateException if the resource scope associated with this instance has been closed
466          * (see {@link #scope()}).
467          * @throws IllegalArgumentException if the given memory layout is not compatible with {@code long}
468          */
469         long vargAsLong(MemoryLayout layout);
470 
471         /**
472          * Reads the next value as a {@code double} and advances this va list's position.
473          *
474          * @param layout the layout of the value
475          * @return the value read as an {@code double}
476          * @throws IllegalStateException if the resource scope associated with this instance has been closed
477          * (see {@link #scope()}).
478          * @throws IllegalArgumentException if the given memory layout is not compatible with {@code double}
479          */
480         double vargAsDouble(MemoryLayout layout);
481 
482         /**
483          * Reads the next value as a {@code MemoryAddress} and advances this va list's position.
484          *
485          * @param layout the layout of the value
486          * @return the value read as an {@code MemoryAddress}
487          * @throws IllegalStateException if the resource scope associated with this instance has been closed
488          * (see {@link #scope()}).
489          * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemoryAddress}
490          */
491         MemoryAddress vargAsAddress(MemoryLayout layout);
492 
493         /**
494          * Reads the next value as a {@code MemorySegment}, and advances this va list's position.
495          * <p>
496          * The memory segment returned by this method will be allocated using the given {@link SegmentAllocator}.
497          *
498          * @param layout the layout of the value
499          * @param allocator the allocator to be used for the native segment allocation
500          * @return the value read as an {@code MemorySegment}
501          * @throws IllegalStateException if the resource scope associated with this instance has been closed
502          * (see {@link #scope()}).
503          * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemorySegment}
504          */
505         MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator);
506 
507         /**
508          * Reads the next value as a {@code MemorySegment}, and advances this va list's position.
509          * <p>
510          * The memory segment returned by this method will be associated with the given {@link ResourceScope}.
511          *
512          * @param layout the layout of the value
513          * @param scope the resource scope to be associated with the returned segment
514          * @return the value read as an {@code MemorySegment}
515          * @throws IllegalStateException if the resource scope associated with this instance has been closed
516          * (see {@link #scope()}).
517          * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemorySegment}
518          * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
519          * than the thread owning {@code scope}.
520          */
521         MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope);
522 
523         /**
524          * Skips a number of elements with the given memory layouts, and advances this va list's position.
525          *
526          * @param layouts the layout of the value
527          * @throws IllegalStateException if the resource scope associated with this instance has been closed
528          * (see {@link #scope()}).
529          */
530         void skip(MemoryLayout... layouts);
531 
532         /**
533          * Returns the resource scope associated with this instance.
534          * @return the resource scope associated with this instance.
535          */
536         ResourceScope scope();
537 
538         /**
539          * Copies this C {@code va_list} at its current position. Copying is useful to traverse the va list's elements
540          * starting from the current position, without affecting the state of the original va list, essentially
541          * allowing the elements to be traversed multiple times.
542          * <p>
543          * Any native resource required by the execution of this method will be allocated in the resource scope
544          * associated with this instance (see {@link #scope()}).
545          * <p>
546          * This method only copies the va list cursor itself and not the memory that may be attached to the
547          * va list which holds its elements. That means that if this va list was created with the
548          * {@link #make(Consumer, ResourceScope)} method, closing this va list will also release the native memory that holds its
549          * elements, making the copy unusable.
550          *
551          * @return a copy of this C {@code va_list}.
552          * @throws IllegalStateException if the resource scope associated with this instance has been closed
553          * (see {@link #scope()}).
554          */
555         VaList copy();
556 
557         /**
558          * Returns the memory address of the C {@code va_list} associated with this instance.
559          * The returned memory address is associated with same resource scope as that associated with this instance.
560          *
561          * @return the memory address of the C {@code va_list} associated with this instance.
562          */
563         @Override
564         MemoryAddress address();
565 
566         /**
567          * Constructs a new {@code VaList} instance out of a memory address pointing to an existing C {@code va_list},
568          * backed by the {@linkplain ResourceScope#globalScope() global} resource scope.
569          * <p>
570          * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
571          * Restricted methods are unsafe, and, if used incorrectly, their use might crash
572          * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
573          * restricted methods, and use safe and supported functionalities, where possible.
574          *
575          * @param address a memory address pointing to an existing C {@code va_list}.
576          * @return a new {@code VaList} instance backed by the C {@code va_list} at {@code address}.
577          * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
578          * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
579          * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
580          */
581         @CallerSensitive
582         static VaList ofAddress(MemoryAddress address) {
583             Reflection.ensureNativeAccess(Reflection.getCallerClass());
584             return SharedUtils.newVaListOfAddress(address, ResourceScope.globalScope());
585         }
586 
587         /**
588          * Constructs a new {@code VaList} instance out of a memory address pointing to an existing C {@code va_list},
589          * with given resource scope.
590          * <p>
591          * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
592          * Restricted methods are unsafe, and, if used incorrectly, their use might crash
593          * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
594          * restricted methods, and use safe and supported functionalities, where possible.
595          *
596          * @param address a memory address pointing to an existing C {@code va_list}.
597          * @param scope the resource scope to be associated with the returned {@code VaList} instance.
598          * @return a new {@code VaList} instance backed by the C {@code va_list} at {@code address}.
599          * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
600          * than the thread owning {@code scope}.
601          * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
602          * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
603          * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
604          */
605         @CallerSensitive
606         static VaList ofAddress(MemoryAddress address, ResourceScope scope) {
607             Reflection.ensureNativeAccess(Reflection.getCallerClass());
608             Objects.requireNonNull(address);
609             Objects.requireNonNull(scope);
610             return SharedUtils.newVaListOfAddress(address, scope);
611         }
612 
613         /**
614          * Constructs a new {@code VaList} using a builder (see {@link Builder}), associated with a given
615          * {@linkplain ResourceScope resource scope}.
616          * <p>
617          * If this method needs to allocate native memory, such memory will be managed by the given
618          * {@linkplain ResourceScope resource scope}, and will be released when the resource scope is {@linkplain ResourceScope#close closed}.
619          * <p>
620          * Note that when there are no elements added to the created va list,
621          * this method will return the same as {@link #empty()}.
622          *
623          * @param actions a consumer for a builder (see {@link Builder}) which can be used to specify the elements
624          *                of the underlying C {@code va_list}.
625          * @param scope the scope to be used for the valist allocation.
626          * @return a new {@code VaList} instance backed by a fresh C {@code va_list}.
627          * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
628          * than the thread owning {@code scope}.
629          */
630         static VaList make(Consumer<Builder> actions, ResourceScope scope) {
631             Objects.requireNonNull(actions);
632             Objects.requireNonNull(scope);
633             return SharedUtils.newVaList(actions, scope);
634         }
635 
636         /**
637          * Returns an empty C {@code va_list} constant.
638          * <p>
639          * The returned {@code VaList} can not be closed.
640          *
641          * @return a {@code VaList} modelling an empty C {@code va_list}.
642          */
643         static VaList empty() {
644             return SharedUtils.emptyVaList();
645         }
646 
647         /**
648          * A builder interface used to construct a C {@code va_list}.
649          *
650          * <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
651          * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
652          */
653         sealed interface Builder permits WinVaList.Builder, SysVVaList.Builder, LinuxAArch64VaList.Builder, MacOsAArch64VaList.Builder {
654 
655             /**
656              * Adds a native value represented as an {@code int} to the C {@code va_list} being constructed.
657              *
658              * @param layout the native layout of the value.
659              * @param value the value, represented as an {@code int}.
660              * @return this builder.
661              * @throws IllegalArgumentException if the given memory layout is not compatible with {@code int}
662              */
663             Builder vargFromInt(ValueLayout layout, int value);
664 
665             /**
666              * Adds a native value represented as a {@code long} to the C {@code va_list} being constructed.
667              *
668              * @param layout the native layout of the value.
669              * @param value the value, represented as a {@code long}.
670              * @return this builder.
671              * @throws IllegalArgumentException if the given memory layout is not compatible with {@code long}
672              */
673             Builder vargFromLong(ValueLayout layout, long value);
674 
675             /**
676              * Adds a native value represented as a {@code double} to the C {@code va_list} being constructed.
677              *
678              * @param layout the native layout of the value.
679              * @param value the value, represented as a {@code double}.
680              * @return this builder.
681              * @throws IllegalArgumentException if the given memory layout is not compatible with {@code double}
682              */
683             Builder vargFromDouble(ValueLayout layout, double value);
684 
685             /**
686              * Adds a native value represented as a {@code MemoryAddress} to the C {@code va_list} being constructed.
687              *
688              * @param layout the native layout of the value.
689              * @param value the value, represented as a {@code Addressable}.
690              * @return this builder.
691              * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemoryAddress}
692              */
693             Builder vargFromAddress(ValueLayout layout, Addressable value);
694 
695             /**
696              * Adds a native value represented as a {@code MemorySegment} to the C {@code va_list} being constructed.
697              *
698              * @param layout the native layout of the value.
699              * @param value the value, represented as a {@code MemorySegment}.
700              * @return this builder.
701              * @throws IllegalArgumentException if the given memory layout is not compatible with {@code MemorySegment}
702              */
703             Builder vargFromSegment(GroupLayout layout, MemorySegment value);
704         }
705     }
706 
707     /**
708      * A C type kind. Each kind corresponds to a particular C language builtin type, and can be attached to
709      * {@link ValueLayout} instances using the {@link MemoryLayout#withAttribute(String, Constable)} in order
710      * to obtain a layout which can be classified accordingly by {@link CLinker#downcallHandle(Addressable, MethodType, FunctionDescriptor)}
711      * and {@link CLinker#upcallStub(MethodHandle, FunctionDescriptor, ResourceScope)}.
712      */
713     enum TypeKind {
714         /**
715          * A kind corresponding to the <em>integral</em> C {@code char} type
716          */
717         CHAR(true),
718         /**
719          * A kind corresponding to the <em>integral</em> C {@code short} type
720          */
721         SHORT(true),
722         /**
723          * A kind corresponding to the <em>integral</em> C {@code int} type
724          */
725         INT(true),
726         /**
727          * A kind corresponding to the <em>integral</em> C {@code long} type
728          */
729         LONG(true),
730         /**
731          * A kind corresponding to the <em>integral</em> C {@code long long} type
732          */
733         LONG_LONG(true),
734         /**
735          * A kind corresponding to the <em>floating-point</em> C {@code float} type
736          */
737         FLOAT(false),
738         /**
739          * A kind corresponding to the <em>floating-point</em> C {@code double} type
740          */
741         DOUBLE(false),
742         /**
743          * A kind corresponding to the an <em>integral</em> C pointer type
744          */
745         POINTER(false);
746 
747         private final boolean isIntegral;
748 
749         TypeKind(boolean isIntegral) {
750             this.isIntegral = isIntegral;
751         }
752 
753         /**
754          * Is this kind integral?
755          *
756          * @return true if this kind is integral
757          */
758         public boolean isIntegral() {
759             return isIntegral;
760         }
761 
762         /**
763          * Is this kind a floating point type?
764          *
765          * @return true if this kind is a floating point type
766          */
767         public boolean isFloat() {
768             return !isIntegral() && !isPointer();
769         }
770 
771         /**
772          * Is this kind a pointer kind?
773          *
774          * @return true if this kind is a pointer kind
775          */
776         public boolean isPointer() {
777             return this == POINTER;
778         }
779 
780         /**
781          * The layout attribute name associated with this classification kind. Clients can retrieve the type kind
782          * of a layout using the following code:
783          * <blockquote><pre>{@code
784         ValueLayout layout = ...
785         TypeKind = layout.attribute(TypeKind.ATTR_NAME).orElse(null);
786          * }</pre></blockquote>
787          */
788         public static final String ATTR_NAME = "abi/kind";
789     }
790 }

  8  *  particular file as subject to the "Classpath" exception as provided
  9  *  by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  *  This code is distributed in the hope that it will be useful, but WITHOUT
 12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 package jdk.incubator.foreign;
 27 



 28 import jdk.internal.foreign.SystemLookup;
 29 import jdk.internal.foreign.abi.SharedUtils;
 30 import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
 31 import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
 32 import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
 33 import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;
 34 import jdk.internal.reflect.CallerSensitive;
 35 import jdk.internal.reflect.Reflection;
 36 

 37 import java.lang.invoke.MethodHandle;
 38 import java.util.Optional;






 39 
 40 /**
 41  * A C linker implements the C Application Binary Interface (ABI) calling conventions.
 42  * Instances of this interface can be used to link foreign functions in native libraries that
 43  * follow the JVM's target platform C ABI. A C linker provides two main capabilities: first, it allows Java code
 44  * to <em>link</em> foreign functions into a so called <em>downcall method handle</em>; secondly, it allows
 45  * native code to call Java method handles via the generation of <em>upcall stubs</em>.




 46  * <p>
 47  * On unsupported platforms this class will fail to initialize with an {@link ExceptionInInitializerError}.





 48  * <p>
 49  * Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
 50  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
 51  *
 52  * <h2><a id = "downcall-method-handles">Downcall method handles</a></h2>

 53  * <p>
 54  * {@linkplain #downcallHandle(FunctionDescriptor) Linking a foreign function} is a process which requires a function descriptor,
 55  * a set of memory layouts which, together, specify the signature of the foreign function to be linked, and returns,
 56  * when complete, a downcall method handle, that is, a method handle that can be used to invoke the target native function.
 57  * The Java {@link java.lang.invoke.MethodType method type} associated with the returned method handle is derived from the
 58  * argument and return layouts in the function descriptor. More specifically, given each layout {@code L} in the
 59  * function descriptor, a corresponding carrier {@code C} is inferred, as described below:
 60  * <ul>
 61  * <li>if {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases:




 62  *     <ul>
 63  *         <li>if {@code L} occurs in a parameter position and {@code E} is {@code MemoryAddress.class},
 64  *         then {@code C = Addressable.class};</li>
 65  *         <li>otherwise, {@code C = E};
 66  *     </ul></li>
 67  * <li>or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>




 68  * </ul>
 69  * <p>
 70  * Arguments of type {@link MemorySegment}, {@link VaList} and {@link NativeSymbol} passed by-reference to a downcall method handle
 71  * are {@linkplain ResourceScope#keepAlive(ResourceScope) kept alive} by the linker implementation. That is, the resource
 72  * scope associated with such arguments cannot be closed, either implicitly or {@linkplain ResourceScope#close() explicitly}
 73  * until the downcall method handle completes.
 74  * <p>
 75  * Furthermore, if the function descriptor's return layout is a group layout, the resulting downcall method handle accepts
 76  * an extra parameter of type {@link SegmentAllocator}, which is used by the linker runtime to allocate the
 77  * memory region associated with the struct returned by  the downcall method handle.
 78  * <p>
 79  * Finally, downcall method handles feature a leading parameter of type {@link NativeSymbol}, from which the
 80  * address of the target native function can be derived. The address, when known statically, can also be provided by
 81  * clients at link time. As for other by-reference parameters (see above) this leading parameter will be
 82  * {@linkplain ResourceScope#keepAlive(ResourceScope) kept alive} by the linker implementation.
 83  * <p>Variadic functions, declared in C either with a trailing ellipses ({@code ...}) at the end of the formal parameter
 84  * list or with an empty formal parameter list, are not supported directly. However, it is possible to link a native
 85  * variadic function by using a {@linkplain FunctionDescriptor#asVariadic(MemoryLayout...) <em>variadic</em>} function descriptor,
 86  * in which the specialized signature of a given variable arity callsite is described in full. Alternatively,
 87  * if the foreign library allows it, clients might also be able to interact with variable arity methods
 88  * using by passing a trailing parameter of type {@link VaList}.




 89  *
 90  * <h2><a id = "upcall-stubs">Upcall stubs</a></h2>
 91  *
 92  * {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, ResourceScope) Creating an upcall stub} requires a method
 93  * handle and a function descriptor; in this case, the set of memory layouts in the function descriptor
 94  * specify the signature of the function pointer associated with the upcall stub.
 95  * <p>
 96  * The type of the provided method handle has to match the Java {@link java.lang.invoke.MethodType method type}
 97  * associated with the upcall stub, which is derived from the argument and return layouts in the function descriptor.
 98  * More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred, as described below:
 99  * <ul>
100  * <li>if {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases:
101  *     <ul>
102  *         <li>if {@code L} occurs in a return position and {@code E} is {@code MemoryAddress.class},
103  *         then {@code C = Addressable.class};</li>
104  *         <li>otherwise, {@code C = E};
105  *     </ul></li>
106  * <li>or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>
107  * </ul>
108  * Upcall stubs are modelled by instances of type {@link NativeSymbol}; upcall stubs can be passed by reference to other
109  * downcall method handles (as {@link NativeSymbol} implements the {@link Addressable} interface) and,
110  * when no longer required, they can be {@link ResourceScope#close() released}, via their {@linkplain NativeSymbol#scope() scope}.
111  *
112  * <h2>System lookup</h2>
113  *
114  * This class implements the {@link SymbolLookup} interface; as such clients can {@linkplain #lookup(String) lookup} symbols
115  * in the standard libraries associated with this linker. The set of symbols available for lookup is unspecified,
116  * as it depends on the platform and on the operating system.
117  *
118  * @implSpec
119  * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
120  */
121 public sealed interface CLinker extends SymbolLookup permits Windowsx64Linker, SysVx64Linker, LinuxAArch64Linker, MacOsAArch64Linker {
122 
123     /**
124      * Returns the C linker for the current platform.
125      * <p>
126      * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
127      * Restricted methods are unsafe, and, if used incorrectly, their use might crash
128      * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
129      * restricted methods, and use safe and supported functionalities, where possible.
130      *
131      * @return a linker for this system.
132      * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
133      * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
134      * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
135      */
136     @CallerSensitive
137     static CLinker systemCLinker() {
138         Reflection.ensureNativeAccess(Reflection.getCallerClass());
139         return SharedUtils.getSystemLinker();
140     }
141 
142     /**
143      * Lookup a symbol in the standard libraries associated with this linker.
144      * The set of symbols available for lookup is unspecified, as it depends on the platform and on the operating system.
145      * @return a linker-specific library lookup which is suitable to find symbols in the standard libraries associated with this linker.








146      */
147     @Override
148     default Optional<NativeSymbol> lookup(String name) {
149         return SystemLookup.getInstance().lookup(name);

150     }
151 
152     /**
153      * Obtains a foreign method handle, with the given type and featuring the given function descriptor,
154      * which can be used to call a target foreign function at the address in the given native symbol.
155      * <p>
156      * If the provided method type's return type is {@code MemorySegment}, then the resulting method handle features
157      * an additional prefix parameter, of type {@link SegmentAllocator}, which will be used by the linker runtime
158      * to allocate structs returned by-value.
159      * <p>
160      * Calling this method is equivalent to the following code:
161 <blockquote><pre>{@code
162     linker.downcallHandle(function).bindTo(symbol);
163 }</pre></blockquote>
164      *
165      * @param symbol   downcall symbol.

166      * @param function the function descriptor.
167      * @return the downcall method handle. The method handle type is <a href="CLinker.html#downcall-method-handles"><em>inferred</em></a>
168      * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout,
169      * or if the symbol is {@link MemoryAddress#NULL}



















170      *
171      * @see SymbolLookup
172      */
173     default MethodHandle downcallHandle(NativeSymbol symbol, FunctionDescriptor function) {
174         SharedUtils.checkSymbol(symbol);
175         return downcallHandle(function).bindTo(symbol);
176     }
177 
178     /**
179      * Obtains a foreign method handle, with the given type and featuring the given function descriptor, which can be
180      * used to call a target foreign function at the address in a dynamically provided native symbol.
181      * The resulting method handle features a prefix parameter (as the first parameter) corresponding to the foreign function
182      * entry point, of type {@link NativeSymbol}.
183      * <p>
184      * If the provided function descriptor's return layout is a {@link GroupLayout}, then the resulting method handle features an
185      * additional prefix parameter (inserted immediately after the address parameter), of type {@link SegmentAllocator}),
186      * which will be used by the linker runtime to allocate structs returned by-value.
187      * <p>
188      * The returned method handle will throw an {@link IllegalArgumentException} if the native symbol passed to it is
189      * associated with the {@link MemoryAddress#NULL} address, or a {@link NullPointerException} if the native symbol is {@code null}.
190      *

191      * @param function the function descriptor.
192      * @return the downcall method handle. The method handle type is <a href="CLinker.html#downcall-method-handles"><em>inferred</em></a>
193      * from the provided function descriptor.
194      * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout.
195      *
196      * @see SymbolLookup
197      */
198     MethodHandle downcallHandle(FunctionDescriptor function);
199 
200     /**
201      * Allocates a native stub with given scope which can be passed to other foreign functions (as a function pointer);
202      * calling such a function pointer from native code will result in the execution of the provided method handle.
203      *
204      * <p>
205      * The returned function pointer is associated with the provided scope. When such scope is closed,
206      * the corresponding native stub will be deallocated.
207      * <p>
208      * The target method handle should not throw any exceptions. If the target method handle does throw an exception,
209      * the VM will exit with a non-zero exit code. To avoid the VM aborting due to an uncaught exception, clients
210      * could wrap all code in the target method handle in a try/catch block that catches any {@link Throwable}, for
211      * instance by using the {@link java.lang.invoke.MethodHandles#catchException(MethodHandle, Class, MethodHandle)}
212      * method handle combinator, and handle exceptions as desired in the corresponding catch block.
213      *
214      * @param target   the target method handle.
215      * @param function the function descriptor.
216      * @param scope the upcall stub scope.
217      * @return the native stub symbol.
218      * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout,
219      * or if it is determined that the target method handle can throw an exception, or if the target method handle
220      * has a type that does not match the upcall stub <a href="CLinker.html#upcall-stubs"><em>inferred type</em></a>.




















































































221      * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
222      * than the thread owning {@code scope}.
223      */
224     NativeSymbol upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope);



















































































































































































































































































































































































































































































225 }
< prev index next >