< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/SharedUtils.java

Print this page

279     }
280 
281     public static String toJavaStringInternal(MemorySegment segment, long start) {
282         int len = strlen(segment, start);
283         byte[] bytes = new byte[len];
284         MemorySegment.copy(segment, JAVA_BYTE, start, bytes, 0, len);
285         return new String(bytes, StandardCharsets.UTF_8);
286     }
287 
288     private static int strlen(MemorySegment segment, long start) {
289         // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int)
290         for (int offset = 0; offset >= 0; offset++) {
291             byte curr = segment.get(JAVA_BYTE, start + offset);
292             if (curr == 0) {
293                 return offset;
294             }
295         }
296         throw new IllegalArgumentException("String too large");
297     }
298 
299     static long bufferCopySize(CallingSequence callingSequence) {
300         // FIXME: > 16 bytes alignment might need extra space since the
301         // starting address of the allocator might be un-aligned.
302         long size = 0;
303         for (int i = 0; i < callingSequence.argumentCount(); i++) {
304             List<Binding> bindings = callingSequence.argumentBindings(i);
305             for (Binding b : bindings) {
306                 if (b instanceof Binding.Copy) {
307                     Binding.Copy c = (Binding.Copy) b;
308                     size = Utils.alignUp(size, c.alignment());
309                     size += c.size();
310                 } else if (b instanceof Binding.Allocate) {
311                     Binding.Allocate c = (Binding.Allocate) b;
312                     size = Utils.alignUp(size, c.alignment());
313                     size += c.size();
314                 }
315             }
316         }
317         return size;
318     }
319 
320     static Map<VMStorage, Integer> indexMap(Binding.Move[] moves) {
321         return IntStream.range(0, moves.length)
322                         .boxed()
323                         .collect(Collectors.toMap(i -> moves[i].storage(), i -> i));
324     }
325 
326     static MethodHandle mergeArguments(MethodHandle mh, int sourceIndex, int destIndex) {
327         MethodType oldType = mh.type();
328         Class<?> sourceType = oldType.parameterType(sourceIndex);
329         Class<?> destType = oldType.parameterType(destIndex);
330         if (sourceType != destType) {
331             // TODO meet?
332             throw new IllegalArgumentException("Parameter types differ: " + sourceType + " != " + destType);
333         }
334         MethodType newType = oldType.dropParameterTypes(destIndex, destIndex + 1);
335         int[] reorder = new int[oldType.parameterCount()];
336         assert destIndex > sourceIndex;

337         for (int i = 0, index = 0; i < reorder.length; i++) {
338             if (i != destIndex) {
339                 reorder[i] = index++;
340             } else {
341                 reorder[i] = sourceIndex;
342             }
343         }
344         return permuteArguments(mh, newType, reorder);
345     }
346 
347 
348     static MethodHandle swapArguments(MethodHandle mh, int firstArg, int secondArg) {
349         MethodType mtype = mh.type();
350         int[] perms = new int[mtype.parameterCount()];
351         MethodType swappedType = MethodType.methodType(mtype.returnType());
352         for (int i = 0 ; i < perms.length ; i++) {
353             int dst = i;
354             if (i == firstArg) dst = secondArg;
355             if (i == secondArg) dst = firstArg;
356             perms[i] = dst;
357             swappedType = swappedType.appendParameterTypes(mtype.parameterType(dst));
358         }
359         return permuteArguments(mh, swappedType, perms);
360     }
361 
362     private static MethodHandle reachabilityFenceHandle(Class<?> type) {
363         return MH_REACHBILITY_FENCE.asType(MethodType.methodType(void.class, type));
364     }
365 
366     static void handleUncaughtException(Throwable t) {
367         if (t != null) {
368             t.printStackTrace();
369             JLA.exit(1);
370         }
371     }
372 
373     static MethodHandle wrapWithAllocator(MethodHandle specializedHandle,
374                                           int allocatorPos, long bufferCopySize,
375                                           boolean upcall) {
376         // insert try-finally to close the NativeScope used for Binding.Copy
377         MethodHandle closer;
378         int insertPos;
379         if (specializedHandle.type().returnType() == void.class) {
380             if (!upcall) {
381                 closer = empty(methodType(void.class, Throwable.class)); // (Throwable) -> void
382             } else {
383                 closer = MH_HANDLE_UNCAUGHT_EXCEPTION;
384             }
385             insertPos = 1;
386         } else {
387             closer = identity(specializedHandle.type().returnType()); // (V) -> V
388             if (!upcall) {
389                 closer = dropArguments(closer, 0, Throwable.class); // (Throwable, V) -> V
390             } else {
391                 closer = collectArguments(closer, 0, MH_HANDLE_UNCAUGHT_EXCEPTION); // (Throwable, V) -> V
392             }
393             insertPos = 2;
394         }
395 
396         // downcalls get the leading NativeSymbol/SegmentAllocator param as well
397         if (!upcall) {
398             closer = collectArguments(closer, insertPos++, reachabilityFenceHandle(NativeSymbol.class));
399             closer = dropArguments(closer, insertPos++, SegmentAllocator.class); // (Throwable, V?, NativeSymbol, SegmentAllocator) -> V/void
400         }
401 
402         closer = collectArguments(closer, insertPos++, MH_CLOSE_CONTEXT); // (Throwable, V?, NativeSymbol?, BindingContext) -> V/void
403 
404         MethodHandle contextFactory;
405 
406         if (bufferCopySize > 0) {
407             contextFactory = MethodHandles.insertArguments(MH_MAKE_CONTEXT_BOUNDED_ALLOCATOR, 0, bufferCopySize);
408         } else if (upcall) {
409             contextFactory = MH_MAKE_CONTEXT_NO_ALLOCATOR;
410         } else {
411             // this path is probably never used now, since ProgrammableInvoker never calls this routine with bufferCopySize == 0
412             contextFactory = constant(Binding.Context.class, Binding.Context.DUMMY);
413         }
414 
415         specializedHandle = tryFinally(specializedHandle, closer);
416         specializedHandle = collectArguments(specializedHandle, allocatorPos, contextFactory);
417         return specializedHandle;
418     }
419 
420     @ForceInline
421     @SuppressWarnings("fallthrough")
422     public static void acquire(Scoped[] args) {
423         ResourceScope scope4 = null;
424         ResourceScope scope3 = null;
425         ResourceScope scope2 = null;
426         ResourceScope scope1 = null;
427         ResourceScope scope0 = null;

541                 acquireHandle = adapter.apply(acquireHandle);
542                 releaseHandle = adapter.apply(releaseHandle);
543             }
544 
545             tryBlock = foldArguments(tryBlock, acquireHandle);
546             cleanup = collectArguments(cleanup, hasReturn ? 2 : 1, releaseHandle);
547 
548             return tryFinally(tryBlock, cleanup);
549         } else {
550             return downcallHandle;
551         }
552     }
553 
554     public static void checkExceptions(MethodHandle target) {
555         Class<?>[] exceptions = JLIA.exceptionTypes(target);
556         if (exceptions != null && exceptions.length != 0) {
557             throw new IllegalArgumentException("Target handle may throw exceptions: " + Arrays.toString(exceptions));
558         }
559     }
560 








561     // lazy init MH_ALLOC and MH_FREE handles
562     private static class AllocHolder {
563 
564         private static final CLinker SYS_LINKER = getSystemLinker();
565 
566         static final MethodHandle MH_MALLOC = SYS_LINKER.downcallHandle(CLinker.systemCLinker().lookup("malloc").get(),
567                 FunctionDescriptor.of(ADDRESS, JAVA_LONG));
568 
569         static final MethodHandle MH_FREE = SYS_LINKER.downcallHandle(CLinker.systemCLinker().lookup("free").get(),
570                 FunctionDescriptor.ofVoid(ADDRESS));
571     }
572 
573     public static void checkSymbol(NativeSymbol symbol) {
574         checkAddressable(symbol, "Symbol is NULL");
575     }
576 
577     public static void checkAddress(MemoryAddress address) {
578         checkAddressable(address, "Address is NULL");
579     }
580 

279     }
280 
281     public static String toJavaStringInternal(MemorySegment segment, long start) {
282         int len = strlen(segment, start);
283         byte[] bytes = new byte[len];
284         MemorySegment.copy(segment, JAVA_BYTE, start, bytes, 0, len);
285         return new String(bytes, StandardCharsets.UTF_8);
286     }
287 
288     private static int strlen(MemorySegment segment, long start) {
289         // iterate until overflow (String can only hold a byte[], whose length can be expressed as an int)
290         for (int offset = 0; offset >= 0; offset++) {
291             byte curr = segment.get(JAVA_BYTE, start + offset);
292             if (curr == 0) {
293                 return offset;
294             }
295         }
296         throw new IllegalArgumentException("String too large");
297     }
298 





















299     static Map<VMStorage, Integer> indexMap(Binding.Move[] moves) {
300         return IntStream.range(0, moves.length)
301                         .boxed()
302                         .collect(Collectors.toMap(i -> moves[i].storage(), i -> i));
303     }
304 
305     static MethodHandle mergeArguments(MethodHandle mh, int sourceIndex, int destIndex) {
306         MethodType oldType = mh.type();
307         Class<?> sourceType = oldType.parameterType(sourceIndex);
308         Class<?> destType = oldType.parameterType(destIndex);
309         if (sourceType != destType) {
310             // TODO meet?
311             throw new IllegalArgumentException("Parameter types differ: " + sourceType + " != " + destType);
312         }
313         MethodType newType = oldType.dropParameterTypes(destIndex, destIndex + 1);
314         int[] reorder = new int[oldType.parameterCount()];
315         if (destIndex < sourceIndex)
316             sourceIndex--;
317         for (int i = 0, index = 0; i < reorder.length; i++) {
318             if (i != destIndex) {
319                 reorder[i] = index++;
320             } else {
321                 reorder[i] = sourceIndex;
322             }
323         }
324         return permuteArguments(mh, newType, reorder);
325     }
326 
327 
328     static MethodHandle swapArguments(MethodHandle mh, int firstArg, int secondArg) {
329         MethodType mtype = mh.type();
330         int[] perms = new int[mtype.parameterCount()];
331         MethodType swappedType = MethodType.methodType(mtype.returnType());
332         for (int i = 0 ; i < perms.length ; i++) {
333             int dst = i;
334             if (i == firstArg) dst = secondArg;
335             if (i == secondArg) dst = firstArg;
336             perms[i] = dst;
337             swappedType = swappedType.appendParameterTypes(mtype.parameterType(dst));
338         }
339         return permuteArguments(mh, swappedType, perms);
340     }
341 
342     private static MethodHandle reachabilityFenceHandle(Class<?> type) {
343         return MH_REACHBILITY_FENCE.asType(MethodType.methodType(void.class, type));
344     }
345 
346     static void handleUncaughtException(Throwable t) {
347         if (t != null) {
348             t.printStackTrace();
349             JLA.exit(1);
350         }
351     }
352 
353     static MethodHandle wrapWithAllocator(MethodHandle specializedHandle,
354                                           int allocatorPos, long allocationSize,
355                                           boolean upcall) {
356         // insert try-finally to close the NativeScope used for Binding.Copy
357         MethodHandle closer;
358         int insertPos;
359         if (specializedHandle.type().returnType() == void.class) {
360             if (!upcall) {
361                 closer = empty(methodType(void.class, Throwable.class)); // (Throwable) -> void
362             } else {
363                 closer = MH_HANDLE_UNCAUGHT_EXCEPTION;
364             }
365             insertPos = 1;
366         } else {
367             closer = identity(specializedHandle.type().returnType()); // (V) -> V
368             if (!upcall) {
369                 closer = dropArguments(closer, 0, Throwable.class); // (Throwable, V) -> V
370             } else {
371                 closer = collectArguments(closer, 0, MH_HANDLE_UNCAUGHT_EXCEPTION); // (Throwable, V) -> V
372             }
373             insertPos = 2;
374         }
375 
376         // downcalls get the leading SegmentAllocator param as well
377         if (!upcall) {
378             closer = dropArguments(closer, insertPos++, SegmentAllocator.class); // (Throwable, V?, SegmentAllocator, NativeSymbol) -> V/void

379         }
380 
381         closer = collectArguments(closer, insertPos, MH_CLOSE_CONTEXT); // (Throwable, V?, SegmentAllocator?, BindingContext) -> V/void
382 
383         MethodHandle contextFactory;
384 
385         if (allocationSize > 0) {
386             contextFactory = MethodHandles.insertArguments(MH_MAKE_CONTEXT_BOUNDED_ALLOCATOR, 0, allocationSize);
387         } else if (upcall) {
388             contextFactory = MH_MAKE_CONTEXT_NO_ALLOCATOR;
389         } else {
390             // this path is probably never used now, since ProgrammableInvoker never calls this routine with bufferCopySize == 0
391             contextFactory = constant(Binding.Context.class, Binding.Context.DUMMY);
392         }
393 
394         specializedHandle = tryFinally(specializedHandle, closer);
395         specializedHandle = collectArguments(specializedHandle, allocatorPos, contextFactory);
396         return specializedHandle;
397     }
398 
399     @ForceInline
400     @SuppressWarnings("fallthrough")
401     public static void acquire(Scoped[] args) {
402         ResourceScope scope4 = null;
403         ResourceScope scope3 = null;
404         ResourceScope scope2 = null;
405         ResourceScope scope1 = null;
406         ResourceScope scope0 = null;

520                 acquireHandle = adapter.apply(acquireHandle);
521                 releaseHandle = adapter.apply(releaseHandle);
522             }
523 
524             tryBlock = foldArguments(tryBlock, acquireHandle);
525             cleanup = collectArguments(cleanup, hasReturn ? 2 : 1, releaseHandle);
526 
527             return tryFinally(tryBlock, cleanup);
528         } else {
529             return downcallHandle;
530         }
531     }
532 
533     public static void checkExceptions(MethodHandle target) {
534         Class<?>[] exceptions = JLIA.exceptionTypes(target);
535         if (exceptions != null && exceptions.length != 0) {
536             throw new IllegalArgumentException("Target handle may throw exceptions: " + Arrays.toString(exceptions));
537         }
538     }
539 
540     public static MethodHandle maybeInsertAllocator(MethodHandle handle) {
541         if (!handle.type().returnType().equals(MemorySegment.class)) {
542             // not returning segment, just insert a throwing allocator
543             handle = insertArguments(handle, 1, THROWING_ALLOCATOR);
544         }
545         return handle;
546     }
547 
548     // lazy init MH_ALLOC and MH_FREE handles
549     private static class AllocHolder {
550 
551         private static final CLinker SYS_LINKER = getSystemLinker();
552 
553         static final MethodHandle MH_MALLOC = SYS_LINKER.downcallHandle(CLinker.systemCLinker().lookup("malloc").get(),
554                 FunctionDescriptor.of(ADDRESS, JAVA_LONG));
555 
556         static final MethodHandle MH_FREE = SYS_LINKER.downcallHandle(CLinker.systemCLinker().lookup("free").get(),
557                 FunctionDescriptor.ofVoid(ADDRESS));
558     }
559 
560     public static void checkSymbol(NativeSymbol symbol) {
561         checkAddressable(symbol, "Symbol is NULL");
562     }
563 
564     public static void checkAddress(MemoryAddress address) {
565         checkAddressable(address, "Address is NULL");
566     }
567 
< prev index next >