< prev index next >

src/java.base/share/classes/jdk/internal/foreign/abi/fallback/FallbackLinker.java

Print this page

 28 import jdk.internal.foreign.MemorySessionImpl;
 29 import jdk.internal.foreign.abi.AbstractLinker;
 30 import jdk.internal.foreign.abi.CapturableState;
 31 import jdk.internal.foreign.abi.LinkerOptions;
 32 import jdk.internal.foreign.abi.SharedUtils;
 33 
 34 import java.lang.foreign.AddressLayout;
 35 import java.lang.foreign.Arena;
 36 import java.lang.foreign.FunctionDescriptor;
 37 import java.lang.foreign.GroupLayout;
 38 import java.lang.foreign.MemoryLayout;
 39 import java.lang.foreign.MemorySegment;
 40 import java.lang.foreign.SegmentAllocator;
 41 import java.lang.foreign.ValueLayout;
 42 import java.lang.invoke.MethodHandle;
 43 import java.lang.invoke.MethodHandles;
 44 import java.lang.invoke.MethodType;
 45 import java.lang.ref.Reference;
 46 import java.nio.ByteOrder;
 47 import java.util.ArrayList;

 48 import java.util.List;

 49 import java.util.function.Consumer;
 50 
 51 import static java.lang.foreign.ValueLayout.ADDRESS;








 52 import static java.lang.invoke.MethodHandles.foldArguments;
 53 
 54 public final class FallbackLinker extends AbstractLinker {
 55 
 56     private static final MethodHandle MH_DO_DOWNCALL;
 57     private static final MethodHandle MH_DO_UPCALL;
 58 
 59     static {
 60         try {
 61             MH_DO_DOWNCALL = MethodHandles.lookup().findStatic(FallbackLinker.class, "doDowncall",
 62                     MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class, FallbackLinker.DowncallData.class));
 63             MH_DO_UPCALL = MethodHandles.lookup().findStatic(FallbackLinker.class, "doUpcall",
 64                     MethodType.methodType(void.class, MethodHandle.class, MemorySegment.class, MemorySegment.class, UpcallData.class));
 65         } catch (ReflectiveOperationException e) {
 66             throw new ExceptionInInitializerError(e);
 67         }
 68     }
 69 
 70     public static FallbackLinker getInstance() {
 71         class Holder {

214             for (int i = 0; i < numArgs; i++) {
215                 MemoryLayout argLayout = argLayouts.get(i);
216                 MemorySegment argPtr = argsSeg.getAtIndex(ADDRESS, i)
217                         .reinterpret(argLayout.byteSize(), upcallArena, null);
218                 args[i] = readValue(argPtr, argLayout);
219             }
220 
221             Object result = target.invokeWithArguments(args);
222 
223             writeValue(result, data.returnLayout(), retSeg);
224         }
225     }
226 
227     // where
228     private static void writeValue(Object arg, MemoryLayout layout, MemorySegment argSeg) {
229         writeValue(arg, layout, argSeg, addr -> {});
230     }
231 
232     private static void writeValue(Object arg, MemoryLayout layout, MemorySegment argSeg,
233                                    Consumer<MemorySegment> acquireCallback) {
234         if (layout instanceof ValueLayout.OfBoolean bl) {
235             argSeg.set(bl, 0, (Boolean) arg);
236         } else if (layout instanceof ValueLayout.OfByte bl) {
237             argSeg.set(bl, 0, (Byte) arg);
238         } else if (layout instanceof ValueLayout.OfShort sl) {
239             argSeg.set(sl, 0, (Short) arg);
240         } else if (layout instanceof ValueLayout.OfChar cl) {
241             argSeg.set(cl, 0, (Character) arg);
242         } else if (layout instanceof ValueLayout.OfInt il) {
243             argSeg.set(il, 0, (Integer) arg);
244         } else if (layout instanceof ValueLayout.OfLong ll) {
245             argSeg.set(ll, 0, (Long) arg);
246         } else if (layout instanceof ValueLayout.OfFloat fl) {
247             argSeg.set(fl, 0, (Float) arg);
248         } else if (layout instanceof ValueLayout.OfDouble dl) {
249             argSeg.set(dl, 0, (Double) arg);
250         } else if (layout instanceof AddressLayout al) {
251             MemorySegment addrArg = (MemorySegment) arg;
252             acquireCallback.accept(addrArg);
253             argSeg.set(al, 0, addrArg);
254         } else if (layout instanceof GroupLayout) {
255             MemorySegment.copy((MemorySegment) arg, 0, argSeg, 0, argSeg.byteSize()); // by-value struct
256         } else {
257             assert layout == null;
258         }
259     }
260 
261     private static Object readValue(MemorySegment seg, MemoryLayout layout) {
262         if (layout instanceof ValueLayout.OfBoolean bl) {
263             return seg.get(bl, 0);
264         } else if (layout instanceof ValueLayout.OfByte bl) {
265             return seg.get(bl, 0);
266         } else if (layout instanceof ValueLayout.OfShort sl) {
267             return seg.get(sl, 0);
268         } else if (layout instanceof ValueLayout.OfChar cl) {
269             return seg.get(cl, 0);
270         } else if (layout instanceof ValueLayout.OfInt il) {
271             return seg.get(il, 0);
272         } else if (layout instanceof ValueLayout.OfLong ll) {
273             return seg.get(ll, 0);
274         } else if (layout instanceof ValueLayout.OfFloat fl) {
275             return seg.get(fl, 0);
276         } else if (layout instanceof ValueLayout.OfDouble dl) {
277             return seg.get(dl, 0);
278         } else if (layout instanceof AddressLayout al) {
279             return seg.get(al, 0);
280         } else if (layout instanceof GroupLayout) {
281             return seg;
282         }
283         assert layout == null;
284         return null;
285     }





































286 }

 28 import jdk.internal.foreign.MemorySessionImpl;
 29 import jdk.internal.foreign.abi.AbstractLinker;
 30 import jdk.internal.foreign.abi.CapturableState;
 31 import jdk.internal.foreign.abi.LinkerOptions;
 32 import jdk.internal.foreign.abi.SharedUtils;
 33 
 34 import java.lang.foreign.AddressLayout;
 35 import java.lang.foreign.Arena;
 36 import java.lang.foreign.FunctionDescriptor;
 37 import java.lang.foreign.GroupLayout;
 38 import java.lang.foreign.MemoryLayout;
 39 import java.lang.foreign.MemorySegment;
 40 import java.lang.foreign.SegmentAllocator;
 41 import java.lang.foreign.ValueLayout;
 42 import java.lang.invoke.MethodHandle;
 43 import java.lang.invoke.MethodHandles;
 44 import java.lang.invoke.MethodType;
 45 import java.lang.ref.Reference;
 46 import java.nio.ByteOrder;
 47 import java.util.ArrayList;
 48 import java.util.HashMap;
 49 import java.util.List;
 50 import java.util.Map;
 51 import java.util.function.Consumer;
 52 
 53 import static java.lang.foreign.ValueLayout.ADDRESS;
 54 import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN;
 55 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
 56 import static java.lang.foreign.ValueLayout.JAVA_CHAR;
 57 import static java.lang.foreign.ValueLayout.JAVA_DOUBLE;
 58 import static java.lang.foreign.ValueLayout.JAVA_FLOAT;
 59 import static java.lang.foreign.ValueLayout.JAVA_INT;
 60 import static java.lang.foreign.ValueLayout.JAVA_LONG;
 61 import static java.lang.foreign.ValueLayout.JAVA_SHORT;
 62 import static java.lang.invoke.MethodHandles.foldArguments;
 63 
 64 public final class FallbackLinker extends AbstractLinker {
 65 
 66     private static final MethodHandle MH_DO_DOWNCALL;
 67     private static final MethodHandle MH_DO_UPCALL;
 68 
 69     static {
 70         try {
 71             MH_DO_DOWNCALL = MethodHandles.lookup().findStatic(FallbackLinker.class, "doDowncall",
 72                     MethodType.methodType(Object.class, SegmentAllocator.class, Object[].class, FallbackLinker.DowncallData.class));
 73             MH_DO_UPCALL = MethodHandles.lookup().findStatic(FallbackLinker.class, "doUpcall",
 74                     MethodType.methodType(void.class, MethodHandle.class, MemorySegment.class, MemorySegment.class, UpcallData.class));
 75         } catch (ReflectiveOperationException e) {
 76             throw new ExceptionInInitializerError(e);
 77         }
 78     }
 79 
 80     public static FallbackLinker getInstance() {
 81         class Holder {

224             for (int i = 0; i < numArgs; i++) {
225                 MemoryLayout argLayout = argLayouts.get(i);
226                 MemorySegment argPtr = argsSeg.getAtIndex(ADDRESS, i)
227                         .reinterpret(argLayout.byteSize(), upcallArena, null);
228                 args[i] = readValue(argPtr, argLayout);
229             }
230 
231             Object result = target.invokeWithArguments(args);
232 
233             writeValue(result, data.returnLayout(), retSeg);
234         }
235     }
236 
237     // where
238     private static void writeValue(Object arg, MemoryLayout layout, MemorySegment argSeg) {
239         writeValue(arg, layout, argSeg, addr -> {});
240     }
241 
242     private static void writeValue(Object arg, MemoryLayout layout, MemorySegment argSeg,
243                                    Consumer<MemorySegment> acquireCallback) {
244         switch (layout) {
245             case ValueLayout.OfBoolean bl -> argSeg.set(bl, 0, (Boolean) arg);
246             case ValueLayout.OfByte    bl -> argSeg.set(bl, 0, (Byte) arg);
247             case ValueLayout.OfShort   sl -> argSeg.set(sl, 0, (Short) arg);
248             case ValueLayout.OfChar    cl -> argSeg.set(cl, 0, (Character) arg);
249             case ValueLayout.OfInt     il -> argSeg.set(il, 0, (Integer) arg);
250             case ValueLayout.OfLong    ll -> argSeg.set(ll, 0, (Long) arg);
251             case ValueLayout.OfFloat   fl -> argSeg.set(fl, 0, (Float) arg);
252             case ValueLayout.OfDouble  dl -> argSeg.set(dl, 0, (Double) arg);
253             case AddressLayout         al -> {
254                 MemorySegment addrArg = (MemorySegment) arg;
255                 acquireCallback.accept(addrArg);
256                 argSeg.set(al, 0, addrArg);
257             }
258             case GroupLayout           __ ->
259                     MemorySegment.copy((MemorySegment) arg, 0, argSeg, 0, argSeg.byteSize()); // by-value struct
260             case null, default -> {
261                 assert layout == null;
262             }





263         }
264     }
265 
266     private static Object readValue(MemorySegment seg, MemoryLayout layout) {
267         if (layout instanceof ValueLayout.OfBoolean bl) {
268             return seg.get(bl, 0);
269         } else if (layout instanceof ValueLayout.OfByte bl) {
270             return seg.get(bl, 0);
271         } else if (layout instanceof ValueLayout.OfShort sl) {
272             return seg.get(sl, 0);
273         } else if (layout instanceof ValueLayout.OfChar cl) {
274             return seg.get(cl, 0);
275         } else if (layout instanceof ValueLayout.OfInt il) {
276             return seg.get(il, 0);
277         } else if (layout instanceof ValueLayout.OfLong ll) {
278             return seg.get(ll, 0);
279         } else if (layout instanceof ValueLayout.OfFloat fl) {
280             return seg.get(fl, 0);
281         } else if (layout instanceof ValueLayout.OfDouble dl) {
282             return seg.get(dl, 0);
283         } else if (layout instanceof AddressLayout al) {
284             return seg.get(al, 0);
285         } else if (layout instanceof GroupLayout) {
286             return seg;
287         }
288         assert layout == null;
289         return null;
290     }
291 
292     @Override
293     public Map<String, MemoryLayout> canonicalLayouts() {
294         return CANONICAL_LAYOUTS;
295     }
296 
297     static final Map<String, MemoryLayout> CANONICAL_LAYOUTS = new HashMap<>();
298 
299     static {
300         CANONICAL_LAYOUTS.put("bool", JAVA_BOOLEAN);
301         CANONICAL_LAYOUTS.put("char", JAVA_BYTE);
302         CANONICAL_LAYOUTS.put("float", JAVA_FLOAT);
303         CANONICAL_LAYOUTS.put("double", JAVA_DOUBLE);
304         CANONICAL_LAYOUTS.put("long long", JAVA_LONG);
305         CANONICAL_LAYOUTS.put("void*", ADDRESS);
306         // platform-dependent sizes
307         CANONICAL_LAYOUTS.put("size_t", FFIType.SIZE_T);
308         CANONICAL_LAYOUTS.put("short", FFIType.layoutFor(LibFallback.shortSize()));
309         CANONICAL_LAYOUTS.put("int", FFIType.layoutFor(LibFallback.intSize()));
310         CANONICAL_LAYOUTS.put("long", FFIType.layoutFor(LibFallback.longSize()));
311         int wchar_size = LibFallback.wcharSize();
312         if (wchar_size == 2) {
313             // prefer JAVA_CHAR
314             CANONICAL_LAYOUTS.put("wchar_t", JAVA_CHAR);
315         } else {
316             CANONICAL_LAYOUTS.put("wchar_t", FFIType.layoutFor(wchar_size));
317         }
318         // JNI types
319         CANONICAL_LAYOUTS.put("jboolean", JAVA_BOOLEAN);
320         CANONICAL_LAYOUTS.put("jchar", JAVA_CHAR);
321         CANONICAL_LAYOUTS.put("jbyte", JAVA_BYTE);
322         CANONICAL_LAYOUTS.put("jshort", JAVA_SHORT);
323         CANONICAL_LAYOUTS.put("jint", JAVA_INT);
324         CANONICAL_LAYOUTS.put("jlong", JAVA_LONG);
325         CANONICAL_LAYOUTS.put("jfloat", JAVA_FLOAT);
326         CANONICAL_LAYOUTS.put("jdouble", JAVA_DOUBLE);
327     }
328 }
< prev index next >