Update ffi namespace for jdk 18

This commit is contained in:
Joshua Suskalo 2022-04-15 13:52:41 -05:00
parent 4037040c4b
commit b10c459bf7
No known key found for this signature in database
GPG key ID: 9B6BA586EFF1B9F0
2 changed files with 51 additions and 42 deletions

View file

@ -17,7 +17,9 @@
Addressable Addressable
CLinker CLinker
FunctionDescriptor FunctionDescriptor
MemoryAddress
MemoryLayout MemoryLayout
NativeSymbol
SegmentAllocator))) SegmentAllocator)))
;;; FFI Code loading and function access ;;; FFI Code loading and function access
@ -33,18 +35,9 @@
(Loader/loadLibrary (.getAbsolutePath (io/file path)))) (Loader/loadLibrary (.getAbsolutePath (io/file path))))
(defn find-symbol (defn find-symbol
"Gets the [[MemoryAddress]] of a symbol from the loaded libraries." "Gets the [[NativeSymbol]] of a symbol from the loaded libraries."
[sym] [sym]
(let [sym (name sym)] (Loader/findSymbol (name sym)))
(Loader/findSymbol sym)))
(defn- method-type
"Gets the [[MethodType]] for a set of `args` and `ret` types."
([args] (method-type args ::mem/void))
([args ret]
(MethodType/methodType
^Class (mem/java-layout ret)
^"[Ljava.lang.Class;" (into-array Class (map mem/java-layout args)))))
(defn- function-descriptor (defn- function-descriptor
"Gets the [[FunctionDescriptor]] for a set of `args` and `ret` types." "Gets the [[FunctionDescriptor]] for a set of `args` and `ret` types."
@ -60,8 +53,8 @@
(defn- downcall-handle (defn- downcall-handle
"Gets the [[MethodHandle]] for the function at the `address`." "Gets the [[MethodHandle]] for the function at the `address`."
[address method-type function-descriptor] [sym function-descriptor]
(.downcallHandle (CLinker/getInstance) address method-type function-descriptor)) (.downcallHandle (CLinker/systemCLinker) sym function-descriptor))
(def ^:private load-instructions (def ^:private load-instructions
"Mapping from primitive types to the instruction used to load them onto the stack." "Mapping from primitive types to the instruction used to load them onto the stack."
@ -138,6 +131,15 @@
[:invokevirtual (prim-classes prim-type) (unbox-fn-for-type prim-type) [prim]]] [:invokevirtual (prim-classes prim-type) (unbox-fn-for-type prim-type) [prim]]]
[])))) []))))
(defn- coerce-addressable
"If the passed `type` is [[MemoryAddress]], returns [[Addressable]], otherwise returns `type`.
This is used to declare the return types of upcall stubs."
[type]
(if (= type MemoryAddress)
Addressable
type))
(defn- downcall-class (defn- downcall-class
"Class definition for an implementation of [[IFn]] which calls a closed over "Class definition for an implementation of [[IFn]] which calls a closed over
method handle without reflection, unboxing primitives when needed." method handle without reflection, unboxing primitives when needed."
@ -174,7 +176,7 @@
args) args)
[:invokevirtual MethodHandle "invokeExact" [:invokevirtual MethodHandle "invokeExact"
(cond->> (cond->>
(conj (mapv insn-layout args) (conj (mapv (comp coerce-addressable insn-layout) args)
(insn-layout ret)) (insn-layout ret))
(not (mem/primitive-type ret)) (cons SegmentAllocator))] (not (mem/primitive-type ret)) (cons SegmentAllocator))]
(to-object-asm ret) (to-object-asm ret)
@ -185,12 +187,12 @@
[handle args ret] [handle args ret]
(insn/new-instance (downcall-class args ret) ^MethodHandle handle)) (insn/new-instance (downcall-class args ret) ^MethodHandle handle))
(defn- ensure-address (defn- ensure-symbol
"Gets the address if the argument is [[Addressable]], otherwise "Gets the address if the argument is [[Addressable]], otherwise
calls [[find-symbol]] on it." calls [[find-symbol]] on it."
[symbol-or-addr] ^NativeSymbol [symbol-or-addr]
(if (instance? Addressable symbol-or-addr) (if (instance? NativeSymbol symbol-or-addr)
(mem/address-of symbol-or-addr) symbol-or-addr
(find-symbol symbol-or-addr))) (find-symbol symbol-or-addr)))
(defn make-downcall (defn make-downcall
@ -205,10 +207,8 @@
first argument of a [[SegmentAllocator]]." first argument of a [[SegmentAllocator]]."
[symbol-or-addr args ret] [symbol-or-addr args ret]
(-> symbol-or-addr (-> symbol-or-addr
ensure-address ensure-symbol
(downcall-handle (downcall-handle (function-descriptor args ret))
(method-type args ret)
(function-descriptor args ret))
(downcall-fn args ret))) (downcall-fn args ret)))
(defn make-varargs-factory (defn make-varargs-factory
@ -440,7 +440,7 @@
arguments." arguments."
[symbol required-args ret] [symbol required-args ret]
(-> symbol (-> symbol
ensure-address ensure-symbol
(make-varargs-factory required-args ret) (make-varargs-factory required-args ret)
(make-serde-varargs-wrapper required-args ret))) (make-serde-varargs-wrapper required-args ret)))
@ -452,7 +452,6 @@
::mem/short :sreturn ::mem/short :sreturn
::mem/int :ireturn ::mem/int :ireturn
::mem/long :lreturn ::mem/long :lreturn
::mem/long-long :lreturn
::mem/char :creturn ::mem/char :creturn
::mem/float :freturn ::mem/float :freturn
::mem/double :dreturn ::mem/double :dreturn
@ -460,7 +459,7 @@
(def ^:private double-sized? (def ^:private double-sized?
"Set of primitive types which require 2 indices in the constant pool." "Set of primitive types which require 2 indices in the constant pool."
#{::mem/double ::mem/long ::mem/long-long}) #{::mem/double ::mem/long})
(defn- upcall-class (defn- upcall-class
"Constructs a class definition for a class with a single method, `upcall`, which "Constructs a class definition for a class with a single method, `upcall`, which
@ -482,7 +481,7 @@
{:name :upcall {:name :upcall
:flags #{:public} :flags #{:public}
:desc (conj (mapv insn-layout arg-types) :desc (conj (mapv insn-layout arg-types)
(insn-layout ret-type)) (coerce-addressable (insn-layout ret-type)))
:emit [[:aload 0] :emit [[:aload 0]
[:getfield :this "upcall_ifn" IFn] [:getfield :this "upcall_ifn" IFn]
(loop [types arg-types (loop [types arg-types
@ -498,7 +497,7 @@
inc))) inc)))
acc)) acc))
[:invokeinterface IFn "invoke" (repeat (inc (count arg-types)) Object)] [:invokeinterface IFn "invoke" (repeat (inc (count arg-types)) Object)]
(to-prim-asm ret-type) (to-prim-asm (coerce-addressable ret-type))
[(return-for-type ret-type :areturn)]]}]}) [(return-for-type ret-type :areturn)]]}]})
(defn- upcall (defn- upcall
@ -506,6 +505,17 @@
[f arg-types ret-type] [f arg-types ret-type]
(insn/new-instance (upcall-class arg-types ret-type) ^IFn f)) (insn/new-instance (upcall-class arg-types ret-type) ^IFn f))
(defn- method-type
"Gets the [[MethodType]] for a set of `args` and `ret` types."
([args] (method-type args ::mem/void))
([args ret]
(MethodType/methodType
^Class (let [r (mem/java-layout ret)]
(if (= r MemoryAddress)
Addressable
r))
^"[Ljava.lang.Class;" (into-array Class (map mem/java-layout args)))))
(defn- upcall-handle (defn- upcall-handle
"Constructs a method handle for invoking `f`, a function of `arg-count` args." "Constructs a method handle for invoking `f`, a function of `arg-count` args."
[f arg-types ret-type] [f arg-types ret-type]
@ -532,7 +542,7 @@
(defmethod mem/serialize* ::fn (defmethod mem/serialize* ::fn
[f [_fn arg-types ret-type & {:keys [raw-fn?]}] scope] [f [_fn arg-types ret-type & {:keys [raw-fn?]}] scope]
(.upcallStub (.upcallStub
(CLinker/getInstance) (CLinker/systemCLinker)
(cond-> f (cond-> f
(not raw-fn?) (upcall-serde-wrapper arg-types ret-type) (not raw-fn?) (upcall-serde-wrapper arg-types ret-type)
:always (upcall-handle arg-types ret-type)) :always (upcall-handle arg-types ret-type))
@ -544,9 +554,8 @@
(when-not (mem/null? addr) (when-not (mem/null? addr)
(vary-meta (vary-meta
(-> addr (-> addr
(downcall-handle (as-> addr (NativeSymbol/ofAddress "coffi_upcall_symbol" addr (mem/connected-scope)))
(method-type arg-types ret-type) (downcall-handle (function-descriptor arg-types ret-type))
(function-descriptor arg-types ret-type))
(downcall-fn arg-types ret-type) (downcall-fn arg-types ret-type)
(cond-> (not raw-fn?) (make-serde-wrapper arg-types ret-type))) (cond-> (not raw-fn?) (make-serde-wrapper arg-types ret-type)))
assoc ::address addr))) assoc ::address addr)))
@ -556,19 +565,16 @@
(defn const (defn const
"Gets the value of a constant stored in `symbol-or-addr`." "Gets the value of a constant stored in `symbol-or-addr`."
[symbol-or-addr type] [symbol-or-addr type]
(mem/deserialize (ensure-address symbol-or-addr) [::mem/pointer type])) (mem/deserialize (.address (ensure-symbol symbol-or-addr)) [::mem/pointer type]))
(deftype StaticVariable [addr type meta] (deftype StaticVariable [seg type meta]
Addressable
(address [_]
addr)
IDeref IDeref
(deref [_] (deref [_]
(mem/deserialize addr [::mem/pointer type])) (mem/deserialize seg type))
IObj IObj
(withMeta [_ meta-map] (withMeta [_ meta-map]
(StaticVariable. addr type (atom meta-map))) (StaticVariable. seg type (atom meta-map)))
IMeta IMeta
(meta [_] (meta [_]
@meta) @meta)
@ -583,7 +589,7 @@
[^StaticVariable static-var newval] [^StaticVariable static-var newval]
(mem/serialize-into (mem/serialize-into
newval (.-type static-var) newval (.-type static-var)
(mem/slice-global (.-addr static-var) (mem/size-of (.-type static-var))) (.-seg static-var)
(mem/global-scope)) (mem/global-scope))
newval) newval)
@ -603,7 +609,10 @@
See [[freset!]], [[fswap!]]." See [[freset!]], [[fswap!]]."
[symbol-or-addr type] [symbol-or-addr type]
(StaticVariable. (ensure-address symbol-or-addr) type (atom nil))) (StaticVariable. (mem/as-segment (.address (ensure-symbol symbol-or-addr))
(mem/size-of type)
(mem/global-scope))
type (atom nil)))
(s/def :coffi.ffi.symbolspec/symbol string?) (s/def :coffi.ffi.symbolspec/symbol string?)
(s/def :coffi.ffi.symbolspec/type keyword?) (s/def :coffi.ffi.symbolspec/type keyword?)

View file

@ -36,8 +36,8 @@ public class Loader {
* *
* @param symbol The name of the symbol to load from a library. * @param symbol The name of the symbol to load from a library.
*/ */
public static MemoryAddress findSymbol(String symbol) { public static NativeSymbol findSymbol(String symbol) {
return CLinker.systemLookup().lookup(symbol) return CLinker.systemCLinker().lookup(symbol)
.orElseGet(() -> SymbolLookup.loaderLookup().lookup(symbol).orElse(null)); .orElseGet(() -> SymbolLookup.loaderLookup().lookup(symbol).orElse(null));
} }
} }