aot: marshal compiled namespaces to bytecode images
Adds src/jolt/aot.janet: save-ns / load-ns-image marshal a namespace's compiled var cells to a Janet bytecode image and load them back, skipping parse/analyze/emit/compile on reload. Compiled functions close over core fns (cfunctions) that can't marshal by value, so we marshal against a dictionary built from the baked-in runtime env (env-lookup jolt-runtime-env, which chains to the Janet boot env): core fns and builtins are referenced by name, only user bytecode and its var cells are serialized. The runtime env is identical at save and load time (same binary), so the dictionaries match. Test round-trips a namespace (constant, fn over it, core-fn user, recursion) into a fresh context and confirms the loaded vars run and stay redefinable.
This commit is contained in:
parent
62c5060093
commit
877373b7e6
2 changed files with 90 additions and 0 deletions
43
test/integration/aot-test.janet
Normal file
43
test/integration/aot-test.janet
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# AOT image round-trip: compile a namespace, marshal it to bytecode, load it into
|
||||
# a FRESH context, and run the loaded functions without recompiling.
|
||||
(use ../../src/jolt/api)
|
||||
(use ../../src/jolt/aot)
|
||||
(use ../../src/jolt/types)
|
||||
|
||||
(print "AOT image round-trip...")
|
||||
|
||||
(def img-path (string (or (os/getenv "TMPDIR") "/tmp") "/jolt-aot-test.jimg"))
|
||||
|
||||
# 1. Compile a namespace into ctx1: a constant, a fn over it, a fn using core
|
||||
# fns, and a recursive fn.
|
||||
(def ctx1 (init {:compile? true}))
|
||||
(ctx-set-current-ns ctx1 "demo")
|
||||
(eval-string ctx1 "(def base 100)")
|
||||
(eval-string ctx1 "(defn add-base [x] (+ x base))")
|
||||
(eval-string ctx1 "(defn sum-sq [xs] (reduce + (map (fn [x] (* x x)) xs)))")
|
||||
(eval-string ctx1 "(defn fact [n] (if (zero? n) 1 (* n (fact (dec n)))))")
|
||||
|
||||
(assert (= 107 (eval-string ctx1 "(add-base 7)")) "ctx1 add-base")
|
||||
(assert (= 14 (eval-string ctx1 "(sum-sq [1 2 3])")) "ctx1 sum-sq")
|
||||
(assert (= 120 (eval-string ctx1 "(fact 5)")) "ctx1 fact")
|
||||
|
||||
# 2. Save an AOT image of the compiled namespace.
|
||||
(save-ns ctx1 "demo" img-path)
|
||||
(assert (os/stat img-path) "image written")
|
||||
|
||||
# 3. Load it into a brand-new context — no recompilation of demo.
|
||||
(def ctx2 (init {:compile? true}))
|
||||
(load-ns-image ctx2 "demo" img-path)
|
||||
(ctx-set-current-ns ctx2 "demo")
|
||||
|
||||
(assert (= 107 (eval-string ctx2 "(add-base 7)")) "ctx2 add-base from image")
|
||||
(assert (= 14 (eval-string ctx2 "(sum-sq [1 2 3])")) "ctx2 sum-sq from image")
|
||||
(assert (= 3628800 (eval-string ctx2 "(fact 10)")) "ctx2 fact from image (new arg)")
|
||||
|
||||
# 4. The loaded vars are live: redefining one is visible to callers compiled in
|
||||
# ctx2 that reference it.
|
||||
(eval-string ctx2 "(def base 1000)")
|
||||
(assert (= 1007 (eval-string ctx2 "(add-base 7)")) "loaded var still redefinable")
|
||||
|
||||
(os/rm img-path)
|
||||
(print "AOT round-trip passed!")
|
||||
Loading…
Add table
Add a link
Reference in a new issue