Initial pass of update to JDK 19

This commit is contained in:
Joshua Suskalo 2022-11-11 13:53:52 -06:00
parent 036d4112fb
commit 3838c0f13c
No known key found for this signature in database
GPG key ID: 9B6BA586EFF1B9F0
5 changed files with 149 additions and 134 deletions

View file

@ -49,11 +49,11 @@
"Compiles java classes required for interop." "Compiles java classes required for interop."
[opts] [opts]
(.mkdirs (io/file class-dir)) (.mkdirs (io/file class-dir))
(b/process {:command-args ["javac" "--add-modules=jdk.incubator.foreign" (b/process {:command-args ["javac" "--enable-preview"
"src/java/coffi/ffi/Loader.java" "src/java/coffi/ffi/Loader.java"
"-d" class-dir "-d" class-dir
"-target" "18" "-target" "19"
"-source" "18"]}) "-source" "19"]})
opts) opts)
(defn- write-pom (defn- write-pom

View file

@ -12,13 +12,13 @@
nodisassemble/nodisassemble {:mvn/version "0.1.3"}} nodisassemble/nodisassemble {:mvn/version "0.1.3"}}
;; NOTE(Joshua): If you want to use nodisassemble you should also add a ;; NOTE(Joshua): If you want to use nodisassemble you should also add a
;; -javaagent for the resolved location ;; -javaagent for the resolved location
:jvm-opts ["--add-modules=jdk.incubator.foreign" "--enable-native-access=ALL-UNNAMED"]} :jvm-opts ["--enable-native-access=ALL-UNNAMED" "--enable-preview"]}
:test {:extra-paths ["test/clj"] :test {:extra-paths ["test/clj"]
:extra-deps {org.clojure/test.check {:mvn/version "1.1.0"} :extra-deps {org.clojure/test.check {:mvn/version "1.1.0"}
io.github.cognitect-labs/test-runner io.github.cognitect-labs/test-runner
{:git/url "https://github.com/cognitect-labs/test-runner" {:git/url "https://github.com/cognitect-labs/test-runner"
:sha "62ef1de18e076903374306060ac0e8a752e57c86"}} :sha "62ef1de18e076903374306060ac0e8a752e57c86"}}
:jvm-opts ["--add-modules=jdk.incubator.foreign" "--enable-native-access=ALL-UNNAMED"] :jvm-opts ["--enable-native-access=ALL-UNNAMED" "--enable-preview"]
:exec-fn cognitect.test-runner.api/test} :exec-fn cognitect.test-runner.api/test}
:codox {:extra-deps {codox/codox {:mvn/version "0.10.7"}} :codox {:extra-deps {codox/codox {:mvn/version "0.10.7"}}
@ -30,8 +30,8 @@
:output-path "docs" :output-path "docs"
:source-uri "https://github.com/IGJoshua/coffi/blob/{git-commit}/{filepath}#L{line}" :source-uri "https://github.com/IGJoshua/coffi/blob/{git-commit}/{filepath}#L{line}"
:metadata {:doc/format :markdown}} :metadata {:doc/format :markdown}}
:jvm-opts ["--add-modules=jdk.incubator.foreign" :jvm-opts ["--add-opens" "java.base/java.lang=ALL-UNNAMED"
"--add-opens" "java.base/java.lang=ALL-UNNAMED"]} "--enable-preview"]}
:build {:replace-deps {org.clojure/clojure {:mvn/version "1.10.3"} :build {:replace-deps {org.clojure/clojure {:mvn/version "1.10.3"}
io.github.clojure/tools.build {:git/tag "v0.3.0" :git/sha "e418fc9"}} io.github.clojure/tools.build {:git/tag "v0.3.0" :git/sha "e418fc9"}}

View file

@ -13,16 +13,17 @@
MethodHandle MethodHandle
MethodHandles MethodHandles
MethodType) MethodType)
(jdk.incubator.foreign (java.lang.foreign
Addressable Addressable
CLinker Linker
FunctionDescriptor FunctionDescriptor
MemoryAddress MemoryAddress
MemoryLayout MemoryLayout
MemorySegment MemorySegment
NativeSymbol
SegmentAllocator))) SegmentAllocator)))
(set! *warn-on-reflection* true)
;;; FFI Code loading and function access ;;; FFI Code loading and function access
(defn load-system-library (defn load-system-library
@ -36,7 +37,7 @@
(Loader/loadLibrary (.getAbsolutePath (io/file path)))) (Loader/loadLibrary (.getAbsolutePath (io/file path))))
(defn find-symbol (defn find-symbol
"Gets the [[NativeSymbol]] of a symbol from the loaded libraries." "Gets the [[MemorySegment]] of a symbol from the loaded libraries."
[sym] [sym]
(Loader/findSymbol (name sym))) (Loader/findSymbol (name sym)))
@ -55,7 +56,7 @@
(defn- downcall-handle (defn- downcall-handle
"Gets the [[MethodHandle]] for the function at the `sym`." "Gets the [[MethodHandle]] for the function at the `sym`."
[sym function-descriptor] [sym function-descriptor]
(.downcallHandle (CLinker/systemCLinker) sym function-descriptor)) (.downcallHandle (Linker/nativeLinker) 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."
@ -186,10 +187,10 @@
(insn/new-instance (downcall-class args ret) ^MethodHandle handle)) (insn/new-instance (downcall-class args ret) ^MethodHandle handle))
(defn- ensure-symbol (defn- ensure-symbol
"Returns the argument if it is a [[NativeSymbol]], otherwise "Returns the argument if it is a [[MemorySegment]], otherwise
calls [[find-symbol]] on it." calls [[find-symbol]] on it."
^NativeSymbol [symbol-or-addr] ^MemorySegment [symbol-or-addr]
(if (instance? NativeSymbol symbol-or-addr) (if (instance? MemorySegment symbol-or-addr)
symbol-or-addr symbol-or-addr
(find-symbol symbol-or-addr))) (find-symbol symbol-or-addr)))
@ -546,7 +547,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/systemCLinker) (Linker/nativeLinker)
(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))
@ -558,7 +559,7 @@
(when-not (mem/null? addr) (when-not (mem/null? addr)
(vary-meta (vary-meta
(-> addr (-> addr
(as-> addr (NativeSymbol/ofAddress "coffi_upcall_symbol" addr (mem/connected-scope))) (MemorySegment/ofAddress mem/pointer-size (mem/connected-scope))
(downcall-handle (function-descriptor arg-types ret-type)) (downcall-handle (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)))

View file

@ -22,32 +22,41 @@
[clojure.set :as set] [clojure.set :as set]
[clojure.spec.alpha :as s]) [clojure.spec.alpha :as s])
(:import (:import
(java.nio ByteOrder) (java.lang.foreign
(jdk.incubator.foreign
Addressable Addressable
MemoryAddress MemoryAddress
MemoryLayout MemoryLayout
MemorySegment MemorySegment
ResourceScope MemorySession
SegmentAllocator SegmentAllocator
ValueLayout ValueLayout
ValueLayout$OfAddress))) ValueLayout$OfByte
ValueLayout$OfShort
ValueLayout$OfInt
ValueLayout$OfLong
ValueLayout$OfChar
ValueLayout$OfFloat
ValueLayout$OfDouble
ValueLayout$OfAddress)
(java.nio ByteOrder)))
(set! *warn-on-reflection* true)
(defn stack-scope (defn stack-scope
"Constructs a new scope for use only in this thread. "Constructs a new scope for use only in this thread.
The memory allocated within this scope is cheap to allocate, like a native The memory allocated within this scope is cheap to allocate, like a native
stack." stack."
^ResourceScope [] ^MemorySession []
(ResourceScope/newConfinedScope)) (MemorySession/openConfined))
(defn shared-scope (defn shared-scope
"Constructs a new shared scope. "Constructs a new shared scope.
This scope can be shared across threads and memory allocated in it will only This scope can be shared across threads and memory allocated in it will only
be cleaned up once every thread accessing the scope closes it." be cleaned up once every thread accessing the scope closes it."
^ResourceScope [] ^MemorySession []
(ResourceScope/newSharedScope)) (MemorySession/openShared))
(defn connected-scope (defn connected-scope
"Constructs a new scope to reclaim all connected resources at once. "Constructs a new scope to reclaim all connected resources at once.
@ -57,8 +66,8 @@
This type of scope cannot be closed, and therefore should not be created in This type of scope cannot be closed, and therefore should not be created in
a [[with-open]] clause." a [[with-open]] clause."
^ResourceScope [] ^MemorySession []
(ResourceScope/newImplicitScope)) (MemorySession/openImplicit))
(defn global-scope (defn global-scope
"Constructs the global scope, which will never reclaim its resources. "Constructs the global scope, which will never reclaim its resources.
@ -67,8 +76,8 @@
memory is allocated with [[alloc]] but is either never freed or whose memory is allocated with [[alloc]] but is either never freed or whose
management is relinquished to a native library, such as when returned from a management is relinquished to a native library, such as when returned from a
callback." callback."
^ResourceScope [] ^MemorySession []
(ResourceScope/globalScope)) (MemorySession/global))
(defn scope-allocator (defn scope-allocator
"Constructs a segment allocator from the given `scope`. "Constructs a segment allocator from the given `scope`.
@ -76,20 +85,21 @@
This is primarily used when working with unwrapped downcall functions. When a This is primarily used when working with unwrapped downcall functions. When a
downcall function returns a non-primitive type, it must be provided with an downcall function returns a non-primitive type, it must be provided with an
allocator." allocator."
^SegmentAllocator [^ResourceScope scope] ^SegmentAllocator [^MemorySession scope]
(SegmentAllocator/nativeAllocator scope)) (SegmentAllocator/newNativeArena scope))
(defn segment-scope (defn segment-scope
"Gets the scope used to construct the `segment`." "Gets the scope used to construct the `segment`."
^ResourceScope [segment] ^MemorySession [segment]
(.scope ^MemorySegment segment)) (.session ^MemorySegment segment))
(defn alloc (defn alloc
"Allocates `size` bytes. "Allocates `size` bytes.
If a `scope` is provided, the allocation will be reclaimed when it is closed." If a `scope` is provided, the allocation will be reclaimed when it is closed."
(^MemorySegment [size] (alloc size (connected-scope))) (^MemorySegment [size] (alloc size (connected-scope)))
(^MemorySegment [size scope] (MemorySegment/allocateNative (long size) ^ResourceScope scope))) (^MemorySegment [size scope] (MemorySegment/allocateNative (long size) ^MemorySession scope))
(^MemorySegment [size alignment scope] (MemorySegment/allocateNative (long size) (long alignment) ^MemorySession scope)))
(defn alloc-with (defn alloc-with
"Allocates `size` bytes using the `allocator`." "Allocates `size` bytes using the `allocator`."
@ -106,10 +116,14 @@
with it wrapped in this." with it wrapped in this."
{:style/indent 1} {:style/indent 1}
[scopes & body] [scopes & body]
`(with-open [scope# (stack-scope)] (if (seq scopes)
(doseq [target-scope# (vec ~scopes)] `(let [scope# ~(first scopes)]
(.keepAlive scope# target-scope#)) (.whileAlive
~@body)) ^MemorySession scope#
(^:once fn* []
(with-acquired [~@(rest scopes)]
~@body))))
`(do ~@body)))
(s/fdef with-acquired (s/fdef with-acquired
:args (s/cat :scopes any? :args (s/cat :scopes any?
:body (s/* any?))) :body (s/* any?)))
@ -154,7 +168,7 @@
(defn add-close-action! (defn add-close-action!
"Adds a 0-arity function to be run when the `scope` closes." "Adds a 0-arity function to be run when the `scope` closes."
[^ResourceScope scope ^Runnable action] [^MemorySession scope ^Runnable action]
(.addCloseAction scope action) (.addCloseAction scope action)
nil) nil)
@ -206,37 +220,37 @@
See [[big-endian]], [[little-endian]]." See [[big-endian]], [[little-endian]]."
(ByteOrder/nativeOrder)) (ByteOrder/nativeOrder))
(def ^ValueLayout byte-layout (def ^ValueLayout$OfByte byte-layout
"The [[MemoryLayout]] for a byte in [[native-endian]] [[ByteOrder]]." "The [[MemoryLayout]] for a byte in [[native-endian]] [[ByteOrder]]."
(MemoryLayout/valueLayout Byte/TYPE native-endian)) ValueLayout/JAVA_BYTE)
(def ^ValueLayout short-layout (def ^ValueLayout$OfShort short-layout
"The [[MemoryLayout]] for a c-sized short in [[native-endian]] [[ByteOrder]]." "The [[MemoryLayout]] for a c-sized short in [[native-endian]] [[ByteOrder]]."
(MemoryLayout/valueLayout Short/TYPE native-endian)) ValueLayout/JAVA_SHORT)
(def ^ValueLayout int-layout (def ^ValueLayout$OfInt int-layout
"The [[MemoryLayout]] for a c-sized int in [[native-endian]] [[ByteOrder]]." "The [[MemoryLayout]] for a c-sized int in [[native-endian]] [[ByteOrder]]."
(MemoryLayout/valueLayout Integer/TYPE native-endian)) ValueLayout/JAVA_INT)
(def ^ValueLayout long-layout (def ^ValueLayout$OfLong long-layout
"The [[MemoryLayout]] for a c-sized long in [[native-endian]] [[ByteOrder]]." "The [[MemoryLayout]] for a c-sized long in [[native-endian]] [[ByteOrder]]."
(MemoryLayout/valueLayout Long/TYPE native-endian)) ValueLayout/JAVA_LONG)
(def ^ValueLayout char-layout (def ^ValueLayout$OfByte char-layout
"The [[MemoryLayout]] for a c-sized char in [[native-endian]] [[ByteOrder]]." "The [[MemoryLayout]] for a c-sized char in [[native-endian]] [[ByteOrder]]."
(MemoryLayout/valueLayout Byte/TYPE native-endian)) ValueLayout/JAVA_BYTE)
(def ^ValueLayout float-layout (def ^ValueLayout$OfFloat float-layout
"The [[MemoryLayout]] for a c-sized float in [[native-endian]] [[ByteOrder]]." "The [[MemoryLayout]] for a c-sized float in [[native-endian]] [[ByteOrder]]."
(MemoryLayout/valueLayout Float/TYPE native-endian)) ValueLayout/JAVA_FLOAT)
(def ^ValueLayout double-layout (def ^ValueLayout$OfDouble double-layout
"The [[MemoryLayout]] for a c-sized double in [[native-endian]] [[ByteOrder]]." "The [[MemoryLayout]] for a c-sized double in [[native-endian]] [[ByteOrder]]."
(MemoryLayout/valueLayout Double/TYPE native-endian)) ValueLayout/JAVA_DOUBLE)
(def ^ValueLayout$OfAddress pointer-layout (def ^ValueLayout$OfAddress pointer-layout
"The [[MemoryLayout]] for a native pointer in [[native-endian]] [[ByteOrder]]." "The [[MemoryLayout]] for a native pointer in [[native-endian]] [[ByteOrder]]."
(MemoryLayout/valueLayout MemoryAddress native-endian)) ValueLayout/ADDRESS)
(def ^long short-size (def ^long short-size
"The size in bytes of a c-sized short." "The size in bytes of a c-sized short."
@ -292,15 +306,15 @@
(fn read-byte-inline (fn read-byte-inline
([segment] ([segment]
`(let [segment# ~segment] `(let [segment# ~segment]
(.get ^MemorySegment segment# ^ValueLayout byte-layout 0))) (.get ^MemorySegment segment# ^ValueLayout$OfByte byte-layout 0)))
([segment offset] ([segment offset]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset] offset# ~offset]
(.get ^MemorySegment segment# ^ValueLayout byte-layout offset#))))} (.get ^MemorySegment segment# ^ValueLayout$OfByte byte-layout offset#))))}
([^MemorySegment segment] ([^MemorySegment segment]
(.get segment ^ValueLayout byte-layout 0)) (.get segment ^ValueLayout$OfByte byte-layout 0))
([^MemorySegment segment ^long offset] ([^MemorySegment segment ^long offset]
(.get segment ^ValueLayout byte-layout offset))) (.get segment ^ValueLayout$OfByte byte-layout offset)))
(defn read-short (defn read-short
"Reads a [[short]] from the `segment`, at an optional `offset`. "Reads a [[short]] from the `segment`, at an optional `offset`.
@ -310,22 +324,22 @@
(fn read-short-inline (fn read-short-inline
([segment] ([segment]
`(let [segment# ~segment] `(let [segment# ~segment]
(.get ^MemorySegment segment# ^ValueLayout short-layout 0))) (.get ^MemorySegment segment# ^ValueLayout$OfShort short-layout 0)))
([segment offset] ([segment offset]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset] offset# ~offset]
(.get ^MemorySegment segment# ^ValueLayout short-layout offset#))) (.get ^MemorySegment segment# ^ValueLayout$OfShort short-layout offset#)))
([segment offset byte-order] ([segment offset byte-order]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order] byte-order# ~byte-order]
(.get ^MemorySegment segment# (.withOrder ^ValueLayout short-layout ^ByteOrder byte-order#) offset#))))} (.get ^MemorySegment segment# (.withOrder ^ValueLayout$OfShort short-layout ^ByteOrder byte-order#) offset#))))}
([^MemorySegment segment] ([^MemorySegment segment]
(.get segment ^ValueLayout short-layout 0)) (.get segment ^ValueLayout$OfShort short-layout 0))
([^MemorySegment segment ^long offset] ([^MemorySegment segment ^long offset]
(.get segment ^ValueLayout short-layout offset)) (.get segment ^ValueLayout$OfShort short-layout offset))
([^MemorySegment segment ^long offset ^ByteOrder byte-order] ([^MemorySegment segment ^long offset ^ByteOrder byte-order]
(.get segment (.withOrder ^ValueLayout short-layout byte-order) offset))) (.get segment (.withOrder ^ValueLayout$OfShort short-layout byte-order) offset)))
(defn read-int (defn read-int
"Reads a [[int]] from the `segment`, at an optional `offset`. "Reads a [[int]] from the `segment`, at an optional `offset`.
@ -335,22 +349,22 @@
(fn read-int-inline (fn read-int-inline
([segment] ([segment]
`(let [segment# ~segment] `(let [segment# ~segment]
(.get ^MemorySegment segment# ^ValueLayout int-layout 0))) (.get ^MemorySegment segment# ^ValueLayout$OfInt int-layout 0)))
([segment offset] ([segment offset]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset] offset# ~offset]
(.get ^MemorySegment segment# ^ValueLayout int-layout offset#))) (.get ^MemorySegment segment# ^ValueLayout$OfInt int-layout offset#)))
([segment offset byte-order] ([segment offset byte-order]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order] byte-order# ~byte-order]
(.get ^MemorySegment segment# (.withOrder ^ValueLayout int-layout ^ByteOrder byte-order#) offset#))))} (.get ^MemorySegment segment# (.withOrder ^ValueLayout$OfInt int-layout ^ByteOrder byte-order#) offset#))))}
([^MemorySegment segment] ([^MemorySegment segment]
(.get segment ^ValueLayout int-layout 0)) (.get segment ^ValueLayout$OfInt int-layout 0))
([^MemorySegment segment ^long offset] ([^MemorySegment segment ^long offset]
(.get segment ^ValueLayout int-layout offset)) (.get segment ^ValueLayout$OfInt int-layout offset))
([^MemorySegment segment ^long offset ^ByteOrder byte-order] ([^MemorySegment segment ^long offset ^ByteOrder byte-order]
(.get segment (.withOrder ^ValueLayout int-layout byte-order) offset))) (.get segment (.withOrder ^ValueLayout$OfInt int-layout byte-order) offset)))
(defn read-long (defn read-long
"Reads a [[long]] from the `segment`, at an optional `offset`. "Reads a [[long]] from the `segment`, at an optional `offset`.
@ -360,22 +374,22 @@
(fn read-long-inline (fn read-long-inline
([segment] ([segment]
`(let [segment# ~segment] `(let [segment# ~segment]
(.get ^MemorySegment segment# ^ValueLayout long-layout 0))) (.get ^MemorySegment segment# ^ValueLayout$OfLong long-layout 0)))
([segment offset] ([segment offset]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset] offset# ~offset]
(.get ^MemorySegment segment# ^ValueLayout long-layout offset#))) (.get ^MemorySegment segment# ^ValueLayout$OfLong long-layout offset#)))
([segment offset byte-order] ([segment offset byte-order]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order] byte-order# ~byte-order]
(.get ^MemorySegment segment# (.withOrder ^ValueLayout long-layout ^ByteOrder byte-order#) offset#))))} (.get ^MemorySegment segment# (.withOrder ^ValueLayout$OfLong long-layout ^ByteOrder byte-order#) offset#))))}
(^long [^MemorySegment segment] (^long [^MemorySegment segment]
(.get segment ^ValueLayout long-layout 0)) (.get segment ^ValueLayout$OfLong long-layout 0))
(^long [^MemorySegment segment ^long offset] (^long [^MemorySegment segment ^long offset]
(.get segment ^ValueLayout long-layout offset)) (.get segment ^ValueLayout$OfLong long-layout offset))
(^long [^MemorySegment segment ^long offset ^ByteOrder byte-order] (^long [^MemorySegment segment ^long offset ^ByteOrder byte-order]
(.get segment (.withOrder ^ValueLayout long-layout byte-order) offset))) (.get segment (.withOrder ^ValueLayout$OfLong long-layout byte-order) offset)))
(defn read-char (defn read-char
"Reads a [[char]] from the `segment`, at an optional `offset`." "Reads a [[char]] from the `segment`, at an optional `offset`."
@ -383,15 +397,15 @@
(fn read-char-inline (fn read-char-inline
([segment] ([segment]
`(let [segment# ~segment] `(let [segment# ~segment]
(char (Byte/toUnsignedInt (.get ^MemorySegment segment# ^ValueLayout byte-layout 0))))) (char (Byte/toUnsignedInt (.get ^MemorySegment segment# ^ValueLayout$OfByte byte-layout 0)))))
([segment offset] ([segment offset]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset] offset# ~offset]
(char (Byte/toUnsignedInt (.get ^MemorySegment segment# ^ValueLayout byte-layout offset#))))))} (char (Byte/toUnsignedInt (.get ^MemorySegment segment# ^ValueLayout$OfByte byte-layout offset#))))))}
([^MemorySegment segment] ([^MemorySegment segment]
(char (Byte/toUnsignedInt (.get segment ^ValueLayout byte-layout 0)))) (char (Byte/toUnsignedInt (.get segment ^ValueLayout$OfChar byte-layout 0))))
([^MemorySegment segment ^long offset] ([^MemorySegment segment ^long offset]
(char (Byte/toUnsignedInt (.get segment ^ValueLayout byte-layout offset))))) (char (Byte/toUnsignedInt (.get segment ^ValueLayout$OfChar byte-layout offset)))))
(defn read-float (defn read-float
"Reads a [[float]] from the `segment`, at an optional `offset`. "Reads a [[float]] from the `segment`, at an optional `offset`.
@ -401,22 +415,22 @@
(fn read-float-inline (fn read-float-inline
([segment] ([segment]
`(let [segment# ~segment] `(let [segment# ~segment]
(.get ^MemorySegment segment# ^ValueLayout float-layout 0))) (.get ^MemorySegment segment# ^ValueLayout$OfFloat float-layout 0)))
([segment offset] ([segment offset]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset] offset# ~offset]
(.get ^MemorySegment segment# ^ValueLayout float-layout offset#))) (.get ^MemorySegment segment# ^ValueLayout$OfFloat float-layout offset#)))
([segment offset byte-order] ([segment offset byte-order]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order] byte-order# ~byte-order]
(.get ^MemorySegment segment# (.withOrder ^ValueLayout float-layout ^ByteOrder byte-order#) offset#))))} (.get ^MemorySegment segment# (.withOrder ^ValueLayout$OfFloat float-layout ^ByteOrder byte-order#) offset#))))}
([^MemorySegment segment] ([^MemorySegment segment]
(.get segment ^ValueLayout float-layout 0)) (.get segment ^ValueLayout$OfFloat float-layout 0))
([^MemorySegment segment ^long offset] ([^MemorySegment segment ^long offset]
(.get segment ^ValueLayout float-layout offset)) (.get segment ^ValueLayout$OfFloat float-layout offset))
([^MemorySegment segment ^long offset ^ByteOrder byte-order] ([^MemorySegment segment ^long offset ^ByteOrder byte-order]
(.get segment (.withOrder ^ValueLayout float-layout byte-order) offset))) (.get segment (.withOrder ^ValueLayout$OfFloat float-layout byte-order) offset)))
(defn read-double (defn read-double
"Reads a [[double]] from the `segment`, at an optional `offset`. "Reads a [[double]] from the `segment`, at an optional `offset`.
@ -426,22 +440,22 @@
(fn read-double-inline (fn read-double-inline
([segment] ([segment]
`(let [segment# ~segment] `(let [segment# ~segment]
(.get ^MemorySegment segment# ^ValueLayout double-layout 0))) (.get ^MemorySegment segment# ^ValueLayout$OfDouble double-layout 0)))
([segment offset] ([segment offset]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset] offset# ~offset]
(.get ^MemorySegment segment# ^ValueLayout double-layout offset#))) (.get ^MemorySegment segment# ^ValueLayout$OfDouble double-layout offset#)))
([segment offset byte-order] ([segment offset byte-order]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order] byte-order# ~byte-order]
(.get ^MemorySegment segment# (.withOrder ^ValueLayout double-layout ^ByteOrder byte-order#) offset#))))} (.get ^MemorySegment segment# (.withOrder ^ValueLayout$OfDouble double-layout ^ByteOrder byte-order#) offset#))))}
(^double [^MemorySegment segment] (^double [^MemorySegment segment]
(.get segment ^ValueLayout double-layout 0)) (.get segment ^ValueLayout$OfDouble double-layout 0))
(^double [^MemorySegment segment ^long offset] (^double [^MemorySegment segment ^long offset]
(.get segment ^ValueLayout double-layout offset)) (.get segment ^ValueLayout$OfDouble double-layout offset))
(^double [^MemorySegment segment ^long offset ^ByteOrder byte-order] (^double [^MemorySegment segment ^long offset ^ByteOrder byte-order]
(.get segment (.withOrder ^ValueLayout double-layout byte-order) offset))) (.get segment (.withOrder ^ValueLayout$OfDouble double-layout byte-order) offset)))
(defn read-address (defn read-address
"Reads a [[MemoryAddress]] from the `segment`, at an optional `offset`." "Reads a [[MemoryAddress]] from the `segment`, at an optional `offset`."
@ -466,16 +480,16 @@
([segment value] ([segment value]
`(let [segment# ~segment `(let [segment# ~segment
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout byte-layout 0 value#))) (.set ^MemorySegment segment# ^ValueLayout$OfByte byte-layout 0 value#)))
([segment offset value] ([segment offset value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout byte-layout offset# value#))))} (.set ^MemorySegment segment# ^ValueLayout$OfByte byte-layout offset# value#))))}
([^MemorySegment segment value] ([^MemorySegment segment value]
(.set segment ^ValueLayout byte-layout 0 ^byte value)) (.set segment ^ValueLayout$OfByte byte-layout 0 ^byte value))
([^MemorySegment segment ^long offset value] ([^MemorySegment segment ^long offset value]
(.set segment ^ValueLayout byte-layout offset ^byte value))) (.set segment ^ValueLayout$OfByte byte-layout offset ^byte value)))
(defn write-short (defn write-short
"Writes a [[short]] to the `segment`, at an optional `offset`. "Writes a [[short]] to the `segment`, at an optional `offset`.
@ -486,24 +500,24 @@
([segment value] ([segment value]
`(let [segment# ~segment `(let [segment# ~segment
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout short-layout 0 value#))) (.set ^MemorySegment segment# ^ValueLayout$OfShort short-layout 0 value#)))
([segment offset value] ([segment offset value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout short-layout offset# value#))) (.set ^MemorySegment segment# ^ValueLayout$OfShort short-layout offset# value#)))
([segment offset byte-order value] ([segment offset byte-order value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order byte-order# ~byte-order
value# ~value] value# ~value]
(.set ^MemorySegment segment# (.withOrder ^ValueLayout short-layout ^ByteOrder byte-order#) offset# value#))))} (.set ^MemorySegment segment# (.withOrder ^ValueLayout$OfShort short-layout ^ByteOrder byte-order#) offset# value#))))}
([^MemorySegment segment value] ([^MemorySegment segment value]
(.set segment ^ValueLayout short-layout 0 ^short value)) (.set segment ^ValueLayout$OfShort short-layout 0 ^short value))
([^MemorySegment segment ^long offset value] ([^MemorySegment segment ^long offset value]
(.set segment ^ValueLayout short-layout offset ^short value)) (.set segment ^ValueLayout$OfShort short-layout offset ^short value))
([^MemorySegment segment ^long offset ^ByteOrder byte-order value] ([^MemorySegment segment ^long offset ^ByteOrder byte-order value]
(.set segment (.withOrder ^ValueLayout short-layout byte-order) offset ^short value))) (.set segment (.withOrder ^ValueLayout$OfShort short-layout byte-order) offset ^short value)))
(defn write-int (defn write-int
"Writes a [[int]] to the `segment`, at an optional `offset`. "Writes a [[int]] to the `segment`, at an optional `offset`.
@ -514,24 +528,24 @@
([segment value] ([segment value]
`(let [segment# ~segment `(let [segment# ~segment
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout int-layout 0 value#))) (.set ^MemorySegment segment# ^ValueLayout$OfInt int-layout 0 value#)))
([segment offset value] ([segment offset value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout int-layout offset# value#))) (.set ^MemorySegment segment# ^ValueLayout$OfInt int-layout offset# value#)))
([segment offset byte-order value] ([segment offset byte-order value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order byte-order# ~byte-order
value# ~value] value# ~value]
(.set ^MemorySegment segment# (.withOrder ^ValueLayout int-layout ^ByteOrder byte-order#) offset# value#))))} (.set ^MemorySegment segment# (.withOrder ^ValueLayout$OfInt int-layout ^ByteOrder byte-order#) offset# value#))))}
([^MemorySegment segment value] ([^MemorySegment segment value]
(.set segment ^ValueLayout int-layout 0 ^int value)) (.set segment ^ValueLayout$OfInt int-layout 0 ^int value))
([^MemorySegment segment ^long offset value] ([^MemorySegment segment ^long offset value]
(.set segment ^ValueLayout int-layout offset ^int value)) (.set segment ^ValueLayout$OfInt int-layout offset ^int value))
([^MemorySegment segment ^long offset ^ByteOrder byte-order value] ([^MemorySegment segment ^long offset ^ByteOrder byte-order value]
(.set segment (.withOrder ^ValueLayout int-layout byte-order) offset ^int value))) (.set segment (.withOrder ^ValueLayout$OfInt int-layout byte-order) offset ^int value)))
(defn write-long (defn write-long
"Writes a [[long]] to the `segment`, at an optional `offset`. "Writes a [[long]] to the `segment`, at an optional `offset`.
@ -542,24 +556,24 @@
([segment value] ([segment value]
`(let [segment# ~segment `(let [segment# ~segment
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout long-layout 0 value#))) (.set ^MemorySegment segment# ^ValueLayout$OfLong long-layout 0 value#)))
([segment offset value] ([segment offset value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout long-layout offset# value#))) (.set ^MemorySegment segment# ^ValueLayout$OfLong long-layout offset# value#)))
([segment offset byte-order value] ([segment offset byte-order value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order byte-order# ~byte-order
value# ~value] value# ~value]
(.set ^MemorySegment segment# (.withOrder ^ValueLayout long-layout ^ByteOrder byte-order#) offset# value#))))} (.set ^MemorySegment segment# (.withOrder ^ValueLayout$OfLong long-layout ^ByteOrder byte-order#) offset# value#))))}
(^long [^MemorySegment segment ^long value] (^long [^MemorySegment segment ^long value]
(.set segment ^ValueLayout long-layout 0 value)) (.set segment ^ValueLayout$OfLong long-layout 0 value))
(^long [^MemorySegment segment ^long offset ^long value] (^long [^MemorySegment segment ^long offset ^long value]
(.set segment ^ValueLayout long-layout offset value)) (.set segment ^ValueLayout$OfLong long-layout offset value))
(^long [^MemorySegment segment ^long offset ^ByteOrder byte-order ^long value] (^long [^MemorySegment segment ^long offset ^ByteOrder byte-order ^long value]
(.set segment (.withOrder ^ValueLayout long-layout byte-order) offset value))) (.set segment (.withOrder ^ValueLayout$OfLong long-layout byte-order) offset value)))
(defn write-char (defn write-char
"Writes a [[char]] to the `segment`, at an optional `offset`." "Writes a [[char]] to the `segment`, at an optional `offset`."
@ -568,22 +582,22 @@
([segment value] ([segment value]
`(let [segment# ~segment `(let [segment# ~segment
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout byte-layout 0 (unchecked-byte (unchecked-int value#))))) (.set ^MemorySegment segment# ^ValueLayout$OfByte byte-layout 0 (unchecked-byte (unchecked-int value#)))))
([segment offset value] ([segment offset value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout byte-layout offset# (unchecked-byte (unchecked-int value#))))))} (.set ^MemorySegment segment# ^ValueLayout$OfByte byte-layout offset# (unchecked-byte (unchecked-int value#))))))}
([^MemorySegment segment value] ([^MemorySegment segment value]
(.set (.set
segment segment
;; HACK(Joshua): The Clojure runtime doesn't have an unchecked-byte cast for ;; HACK(Joshua): The Clojure runtime doesn't have an unchecked-byte cast for
;; characters, so this double cast is necessary unless I emit ;; characters, so this double cast is necessary unless I emit
;; my own bytecode with insn. ;; my own bytecode with insn.
^ValueLayout byte-layout 0 ^ValueLayout$OfByte byte-layout 0
(unchecked-byte (unchecked-int ^char value)))) (unchecked-byte (unchecked-int ^char value))))
([^MemorySegment segment ^long offset value] ([^MemorySegment segment ^long offset value]
(.set segment ^ValueLayout byte-layout offset (unchecked-byte (unchecked-int ^char value))))) (.set segment ^ValueLayout$OfByte byte-layout offset (unchecked-byte (unchecked-int ^char value)))))
(defn write-float (defn write-float
"Writes a [[float]] to the `segment`, at an optional `offset`. "Writes a [[float]] to the `segment`, at an optional `offset`.
@ -594,24 +608,24 @@
([segment value] ([segment value]
`(let [segment# ~segment `(let [segment# ~segment
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout float-layout 0 value#))) (.set ^MemorySegment segment# ^ValueLayout$OfFloat float-layout 0 value#)))
([segment offset value] ([segment offset value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout float-layout offset# value#))) (.set ^MemorySegment segment# ^ValueLayout$OfFloat float-layout offset# value#)))
([segment offset byte-order value] ([segment offset byte-order value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order byte-order# ~byte-order
value# ~value] value# ~value]
(.set ^MemorySegment segment# (.withOrder ^ValueLayout float-layout ^ByteOrder byte-order#) offset# value#))))} (.set ^MemorySegment segment# (.withOrder ^ValueLayout$OfFloat float-layout ^ByteOrder byte-order#) offset# value#))))}
([^MemorySegment segment value] ([^MemorySegment segment value]
(.set segment ^ValueLayout float-layout 0 ^float value)) (.set segment ^ValueLayout$OfFloat float-layout 0 ^float value))
([^MemorySegment segment ^long offset value] ([^MemorySegment segment ^long offset value]
(.set segment ^ValueLayout float-layout offset ^float value)) (.set segment ^ValueLayout$OfFloat float-layout offset ^float value))
([^MemorySegment segment ^long offset ^ByteOrder byte-order value] ([^MemorySegment segment ^long offset ^ByteOrder byte-order value]
(.set segment (.withOrder ^ValueLayout float-layout byte-order) offset ^float value))) (.set segment (.withOrder ^ValueLayout$OfFloat float-layout byte-order) offset ^float value)))
(defn write-double (defn write-double
"Writes a [[double]] to the `segment`, at an optional `offset`. "Writes a [[double]] to the `segment`, at an optional `offset`.
@ -622,24 +636,24 @@
([segment value] ([segment value]
`(let [segment# ~segment `(let [segment# ~segment
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout double-layout 0 value#))) (.set ^MemorySegment segment# ^ValueLayout$OfDouble double-layout 0 value#)))
([segment offset value] ([segment offset value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
value# ~value] value# ~value]
(.set ^MemorySegment segment# ^ValueLayout double-layout offset# value#))) (.set ^MemorySegment segment# ^ValueLayout$OfDouble double-layout offset# value#)))
([segment offset byte-order value] ([segment offset byte-order value]
`(let [segment# ~segment `(let [segment# ~segment
offset# ~offset offset# ~offset
byte-order# ~byte-order byte-order# ~byte-order
value# ~value] value# ~value]
(.set ^MemorySegment segment# (.withOrder ^ValueLayout double-layout ^ByteOrder byte-order#) offset# value#))))} (.set ^MemorySegment segment# (.withOrder ^ValueLayout$OfDouble double-layout ^ByteOrder byte-order#) offset# value#))))}
(^double [^MemorySegment segment ^double value] (^double [^MemorySegment segment ^double value]
(.set segment ^ValueLayout double-layout 0 value)) (.set segment ^ValueLayout$OfDouble double-layout 0 value))
(^double [^MemorySegment segment ^long offset ^double value] (^double [^MemorySegment segment ^long offset ^double value]
(.set segment ^ValueLayout double-layout offset value)) (.set segment ^ValueLayout$OfDouble double-layout offset value))
(^double [^MemorySegment segment ^long offset ^ByteOrder byte-order ^double value] (^double [^MemorySegment segment ^long offset ^ByteOrder byte-order ^double value]
(.set segment (.withOrder ^ValueLayout double-layout byte-order) offset value))) (.set segment (.withOrder ^ValueLayout$OfDouble double-layout byte-order) offset value)))
(defn write-address (defn write-address
"Writes a [[MemoryAddress]] to the `segment`, at an optional `offset`." "Writes a [[MemoryAddress]] to the `segment`, at an optional `offset`."
@ -822,7 +836,7 @@
(defn alloc-instance (defn alloc-instance
"Allocates a memory segment for the given `type`." "Allocates a memory segment for the given `type`."
(^MemorySegment [type] (alloc-instance type (connected-scope))) (^MemorySegment [type] (alloc-instance type (connected-scope)))
(^MemorySegment [type scope] (MemorySegment/allocateNative ^long (size-of type) ^ResourceScope scope))) (^MemorySegment [type scope] (MemorySegment/allocateNative ^long (size-of type) ^MemorySession scope)))
(declare serialize serialize-into) (declare serialize serialize-into)

View file

@ -1,6 +1,6 @@
package coffi.ffi; package coffi.ffi;
import jdk.incubator.foreign.*; import java.lang.foreign.*;
/** /**
* Loading libraries with the {@link System#load} and {@link System#loadLibrary} * Loading libraries with the {@link System#load} and {@link System#loadLibrary}
@ -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 NativeSymbol findSymbol(String symbol) { public static MemorySegment findSymbol(String symbol) {
return CLinker.systemCLinker().lookup(symbol) return Linker.nativeLinker().defaultLookup().lookup(symbol)
.orElseGet(() -> SymbolLookup.loaderLookup().lookup(symbol).orElse(null)); .orElseGet(() -> SymbolLookup.loaderLookup().lookup(symbol).orElse(null));
} }
} }