~ chicken-core (chicken-5) db3d4f5f3de9a0adacbb70fef5d2ba6e4817de32
commit db3d4f5f3de9a0adacbb70fef5d2ba6e4817de32
Author: Peter Bex <peter@more-magic.net>
AuthorDate: Tue Jun 20 16:57:44 2023 +0200
Commit: Peter Bex <peter@more-magic.net>
CommitDate: Fri Jun 23 13:42:35 2023 +0200
Convert line number db hash table to use weak alists for form lookup
This doesn't turn it into a proper weak hash table (where the keys
would be weak), but the entries themselves are alists which are used
for further lookup of the source expression. The symbol which is in
the car of an expression is used as the key in the hash table.
This means that the source expression may be collected. This will
happen for instance when the symbol is redefined, like when reloading
a source file. This means the majority of memory will be reclaimable,
and storing source locations in the interpreter will be safe.
We also clean out broken weak pointers whenever entries get added or
looked up so it doesn't grow out of proportion. This is suboptimal,
as expressions can be added *without* traversing the alist. This
turns O(1) entry addition into O(n) addition, or quadratic behaviour
over the number of added entries with the same car. However, it *has*
to be done there, otherwise reloading code over and over still results
in an ever-expanding line number db.
To improve this, perhaps we can come up with some sort of "expression
hash" instead, which hashes the entire source expression, to avoid
alist usage?
diff --git a/eval.scm b/eval.scm
index b5671e9a..86792a7a 100644
--- a/eval.scm
+++ b/eval.scm
@@ -121,7 +121,8 @@
(define (emit-syntax-trace-info tf info cntr)
(when tf
(##core#inline
- "C_emit_syntax_trace_info"
+ "C_emit_trace_info"
+ (or (get-line-number info) "<syntax>")
info
cntr
(thread-id ##sys#current-thread) ) ) )
diff --git a/expand.scm b/expand.scm
index 0567e8d5..d809c4f8 100644
--- a/expand.scm
+++ b/expand.scm
@@ -718,15 +718,30 @@
;;; Hook for source information
+(define (alist-weak-cons k v lst)
+ (cons (##core#inline_allocate ("C_a_i_weak_cons" 3) k v) lst))
+
+(define (assq/drop-bwp! x lst)
+ (let lp ((lst lst)
+ (prev #f))
+ (cond ((null? lst) #f)
+ ((eq? x (caar lst)) (car lst))
+ ((and prev
+ (##core#inline "C_bwpp" (caar lst)))
+ (set-cdr! prev (cdr lst))
+ (lp (cdr lst) prev))
+ (else (lp (cdr lst) lst)))))
+
(define (##sys#read/source-info-hook class data val) ; Used here, in core.scm and in csi.scm
(when (and (eq? 'list-info class) (symbol? (car data)))
- (hash-table-set!
- ##sys#line-number-database
- (car data)
- (alist-cons
- data (conc ##sys#current-source-filename ":" val)
- (or (hash-table-ref ##sys#line-number-database (car data))
- '() ) ) ) )
+ (let ((old-value (or (hash-table-ref ##sys#line-number-database (car data)) '())))
+ (assq/drop-bwp! (car data) old-value) ;; Hack to clean out garbage values
+ (hash-table-set!
+ ##sys#line-number-database
+ (car data)
+ (alist-weak-cons
+ data (conc ##sys#current-source-filename ":" val)
+ old-value ) )) )
data)
;; TODO: Should we export this, or something like it?
@@ -741,7 +756,7 @@
(and (symbol? head)
(cond ((hash-table-ref ##sys#line-number-database head)
=> (lambda (pl)
- (let ((a (assq sexp pl)))
+ (let ((a (assq/drop-bwp! sexp pl)))
(and a (cdr a)))))
(else #f))))))
@@ -749,7 +764,7 @@
(define (##sys#get-line-2 exp)
(let* ((name (car exp))
(lst (hash-table-ref ##sys#line-number-database name)))
- (cond ((and lst (assq exp (cdr lst)))
+ (cond ((and lst (assq/drop-bwp! exp (cdr lst)))
=> (lambda (a) (values (car lst) (cdr a))) )
(else (values name #f)) ) ) )
@@ -864,7 +879,7 @@
(cur (or (hash-table-ref ##sys#line-number-database name) '())) )
(unless (assq new cur)
(hash-table-set! ##sys#line-number-database name
- (alist-cons new ln cur))))
+ (alist-weak-cons new ln cur))))
new)
(assert (list? se) "not a list" se) ;XXX remove later
(define (rename sym)
Trap