diff --git a/CHANGELOG.md b/CHANGELOG.md index 566381f..251df24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. This change - New `coffi.mem/null` var for implementing custom types ### Performance +- Upcall functions serialized from functions returned by deserializing function pointers now use the backing function pointer directly - Upcall and downcall classes have been changed to be memoized, meaning ASM is no longer invoked every time a function is serialized, which should drastically improve performance where functions are serialized in a hot loop ### Fixed diff --git a/src/clj/coffi/ffi.clj b/src/clj/coffi/ffi.clj index bcac52b..d6e72fd 100644 --- a/src/clj/coffi/ffi.clj +++ b/src/clj/coffi/ffi.clj @@ -575,25 +575,31 @@ (mem/global-arena)))) (defmethod mem/serialize* ::fn - [f [_fn arg-types ret-type & {:keys [raw-fn?]}] arena] - (.upcallStub - (Linker/nativeLinker) - ^MethodHandle (cond-> f - (not raw-fn?) (upcall-serde-wrapper arg-types ret-type) - :always (upcall-handle arg-types ret-type)) - ^FunctionDescriptor (function-descriptor arg-types ret-type) - ^Arena arena - (make-array Linker$Option 0))) + [f [_fn arg-types ret-type & {:keys [raw-fn?]} :as typ] arena] + (if-let [address (::address (meta f))] + (do (assert (= typ (::type (meta f))) + "The type of a deserialized function must match the type it is re-serialized to.") + address) + (.upcallStub + (Linker/nativeLinker) + ^MethodHandle (cond-> f + (not raw-fn?) (upcall-serde-wrapper arg-types ret-type) + :always (upcall-handle arg-types ret-type)) + ^FunctionDescriptor (function-descriptor arg-types ret-type) + ^Arena arena + (make-array Linker$Option 0)))) (defmethod mem/deserialize* ::fn - [addr [_fn arg-types ret-type & {:keys [raw-fn?]}]] + [addr [_fn arg-types ret-type & {:keys [raw-fn?] :as typ}]] (when-not (mem/null? addr) (vary-meta (-> ^MemorySegment addr (downcall-handle (function-descriptor arg-types ret-type)) (downcall-fn arg-types ret-type) (cond-> (not raw-fn?) (make-serde-wrapper arg-types ret-type))) - assoc ::address addr))) + assoc + ::address addr + ::type typ))) ;;; Static memory access