From db3d4f5f3de9a0adacbb70fef5d2ba6e4817de32 Mon Sep 17 00:00:00 2001 From: Peter Bex Date: Tue, 20 Jun 2023 16:57:44 +0200 Subject: [PATCH 3/6] 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? --- eval.scm | 3 ++- expand.scm | 35 +++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 11 deletions(-) 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) "") 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) -- 2.40.1