Update ffi namespace for jdk 18
This commit is contained in:
parent
4037040c4b
commit
b10c459bf7
2 changed files with 51 additions and 42 deletions
|
|
@ -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?)
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue