Direct-linking for closed-world builds (jolt build)
A release/optimized `jolt build` is a closed world: every app def is final, so an app->app call can bind to the def's Scheme binding directly instead of going through (jolt-invoke (var-deref ns name)). The emitter gains a direct-link mode (off for the seed mint, runtime -e/repl, and dev builds). With it on, a top-level app def also emits a binding jv$<ns>$<name> that def-var! aliases; an app->app call or value-ref to a name already emitted in the unit lowers to that binding, skipping both the var-table lookup and the generic IFn dispatch. ^:dynamic/^:redef defs and nested defs (a defonce's inner def) opt out and stay indirect. Off direct-link mode, emit-top-form is exactly emit, so the seed and runtime eval are byte-unchanged (selfhost holds). build.ss turns it on for release + optimized; the defined-set accumulates across the dependency-ordered namespaces so a dep's defs are linkable by the time the entry that calls them is emitted. App->core calls stay indirect for now (core is the baked seed); that's a later stage. ~1.74x on a hot cross-namespace call loop (26.5s -> 15.2s).
This commit is contained in:
parent
9a68f96b6c
commit
7bc277b2e8
6 changed files with 283 additions and 95 deletions
|
|
@ -225,11 +225,19 @@
|
|||
" — is it on the source roots?")))
|
||||
;; 2. emit each app namespace. `optimized` turns on the inference + flatten
|
||||
;; + scalar-replace passes (closed world); release/dev get const-fold only.
|
||||
;; release + optimized are closed-world: turn on direct-linking so app->app
|
||||
;; calls bind directly (dev stays open/indirect). The defined-set accumulates
|
||||
;; across the dependency-ordered namespaces, so a dep's defs are direct-linkable
|
||||
;; by the time the entry that calls them is emitted.
|
||||
(set-optimize! (string=? mode "optimized"))
|
||||
(let ((dl (not (string=? mode "dev"))))
|
||||
((var-deref "jolt.backend-scheme" "set-direct-link!") dl)
|
||||
((var-deref "jolt.backend-scheme" "direct-link-reset!")))
|
||||
(let* ((app-strs (apply append
|
||||
(map (lambda (nf) (bld-emit-ns (car nf) (read-file-string (cdr nf))))
|
||||
ordered)))
|
||||
(_ (set-optimize! #f))
|
||||
(_ ((var-deref "jolt.backend-scheme" "set-direct-link!") #f))
|
||||
(builddir (string-append out-path ".build"))
|
||||
(flat-ss (string-append builddir "/flat.ss"))
|
||||
(flat-so (string-append builddir "/flat.so"))
|
||||
|
|
|
|||
|
|
@ -37,10 +37,13 @@
|
|||
;; (mark-macro! ns name) so the on-Chez analyzer can expand it.
|
||||
;; Analyze -> (optionally run passes) -> emit one form. optimize? runs
|
||||
;; jolt.passes/run-passes (build optimizes; the seed minter stays un-optimized so
|
||||
;; the self-host fixpoint is independent of the passes).
|
||||
;; the self-host fixpoint is independent of the passes). emit-top-form is the
|
||||
;; top-level entry: in direct-link mode it binds jv$<fqn> for a top-level def; off
|
||||
;; that mode (the minter, runtime eval) it is exactly emit, so output is unchanged.
|
||||
(define jolt-ce-emit-top (var-deref "jolt.backend-scheme" "emit-top-form"))
|
||||
(define (ei-compile-form ctx f optimize?)
|
||||
(let ((ir (jolt-ce-analyze ctx f)))
|
||||
(jolt-ce-emit (if optimize? (jolt-ce-run-passes ir ctx) ir))))
|
||||
(jolt-ce-emit-top (if optimize? (jolt-ce-run-passes ir ctx) ir))))
|
||||
|
||||
;; The emitted `(def-var! …)(mark-macro! …)` pair for a defmacro, guard-wrapped
|
||||
;; (tolerant) or bare (strict) to match guard?.
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue