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 }
|