commit 981f61e8f53007812c4d6cb9cdac887f26e4f529
parent f56fbdf806233d2fa60d837b415f909d71ef10a6
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Tue, 5 May 2026 16:20:21 -0700
cc: %cg-fn-set! mutates in place instead of alist-update rebuild
Hot-path write was doing assoc + append + reverse + n fresh conses on
every key update; cg-fn-begin/v and per-expression emits hammer it.
Now: assq, set-cdr! on hit, prepend on miss. No allocation on update.
Diffstat:
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/cc/cc.scm b/cc/cc.scm
@@ -2634,8 +2634,17 @@
;; Per-fn metadata (name, ret-slot, ret-type, switch-case lists, ...)
;; lives on cg-fn-meta, reset at every cg-fn-begin/v.
+;;
+;; Update is destructive: assq for the key, set-cdr! if found, else
+;; prepend. The functional alist-update path was O(n) per write *with*
+;; an append+reverse rebuild — and cg-fn-begin/v plus every emit in a
+;; function body hammers this. Mutation here is safe: the meta alist
+;; is private to one cg, scratch-only, and discarded at fn-end.
(define (%cg-fn-set! cg key val)
- (cg-fn-meta-set! cg (alist-update key (lambda (_) val) (cg-fn-meta cg))))
+ (let* ((meta (cg-fn-meta cg))
+ (p (assq key meta)))
+ (cond (p (set-cdr! p val))
+ (else (cg-fn-meta-set! cg (cons (cons key val) meta))))))
(define (%cg-fn-get cg key) (alist-ref/eq key (cg-fn-meta cg)))