mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
when leaving a non-tail let, allow bound vals to be collected
* module/language/tree-il/compile-glil.scm (flatten-lambda-case): Clear lexical stack slots at the end of a non-tail let, letrec, or fix. Fixes http://debbugs.gnu.org/9900. * test-suite/tests/gc.test ("gc"): Add test.
This commit is contained in:
parent
acdf4fcc05
commit
fb135e12a4
2 changed files with 41 additions and 9 deletions
|
@ -237,6 +237,24 @@
|
|||
(if (eq? context 'tail)
|
||||
(emit-code #f (make-glil-call 'return 1)))))
|
||||
|
||||
;; After lexical binding forms in non-tail context, call this
|
||||
;; function to clear stack slots, allowing their previous values to
|
||||
;; be collected.
|
||||
(define (clear-stack-slots context syms)
|
||||
(case context
|
||||
((push drop)
|
||||
(for-each (lambda (v)
|
||||
(and=>
|
||||
;; Can be #f if the var is labels-allocated.
|
||||
(hashq-ref allocation v)
|
||||
(lambda (h)
|
||||
(pmatch (hashq-ref h self)
|
||||
((#t _ . ,n)
|
||||
(emit-code #f (make-glil-void))
|
||||
(emit-code #f (make-glil-lexical #t #f 'set n)))
|
||||
(,loc (error "bad let var allocation" x loc))))))
|
||||
syms))))
|
||||
|
||||
(record-case x
|
||||
((<void>)
|
||||
(case context
|
||||
|
@ -802,6 +820,7 @@
|
|||
(,loc (error "bad let var allocation" x loc))))
|
||||
(reverse gensyms))
|
||||
(comp-tail body)
|
||||
(clear-stack-slots context gensyms)
|
||||
(emit-code #f (make-glil-unbind)))
|
||||
|
||||
((<letrec> src in-order? names gensyms vals body)
|
||||
|
@ -834,6 +853,7 @@
|
|||
(,loc (error "bad letrec var allocation" x loc))))
|
||||
(reverse gensyms))))
|
||||
(comp-tail body)
|
||||
(clear-stack-slots context gensyms)
|
||||
(emit-code #f (make-glil-unbind)))
|
||||
|
||||
((<fix> src names gensyms vals body)
|
||||
|
@ -922,6 +942,7 @@
|
|||
(comp-tail body)
|
||||
(if new-RA
|
||||
(emit-label new-RA))
|
||||
(clear-stack-slots context gensyms)
|
||||
(emit-code #f (make-glil-unbind))))
|
||||
|
||||
((<let-values> src exp body)
|
||||
|
@ -947,6 +968,7 @@
|
|||
(,loc (error "bad let-values var allocation" x loc))))
|
||||
(reverse gensyms))
|
||||
(comp-tail body)
|
||||
(clear-stack-slots context gensyms)
|
||||
(emit-code #f (make-glil-unbind))))))
|
||||
|
||||
;; much trickier than i thought this would be, at first, due to the need
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
;;;; License along with this library; if not, write to the Free Software
|
||||
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
(use-modules (ice-9 documentation)
|
||||
(test-suite lib))
|
||||
(define-module (test-suite tests gc)
|
||||
#:use-module (ice-9 documentation)
|
||||
#:use-module (test-suite lib)
|
||||
#:use-module ((system base compile) #:select (compile)))
|
||||
|
||||
|
||||
;;;
|
||||
|
@ -62,10 +64,8 @@
|
|||
(add-hook! after-gc-hook thunk)
|
||||
(gc)
|
||||
(remove-hook! after-gc-hook thunk)
|
||||
foo)))
|
||||
foo))
|
||||
|
||||
|
||||
(with-test-prefix "gc"
|
||||
(pass-if "Unused modules are removed"
|
||||
(let* ((guard (make-guardian))
|
||||
(total 1000))
|
||||
|
@ -76,12 +76,22 @@
|
|||
(stack-cleanup 20)
|
||||
|
||||
(gc)
|
||||
(gc) ;; twice: have to kill the weak vectors.
|
||||
(gc) ;; thrice: because the test doesn't succeed with only
|
||||
;; one gc round. not sure why.
|
||||
(gc) ;; twice: have to kill the weak vectors.
|
||||
(gc) ;; thrice: because the test doesn't succeed with only
|
||||
;; one gc round. not sure why.
|
||||
|
||||
(= (let lp ((i 0))
|
||||
(if (guard)
|
||||
(lp (1+ i))
|
||||
i))
|
||||
total))))
|
||||
total)))
|
||||
|
||||
(pass-if "Lexical vars are collectable"
|
||||
(procedure?
|
||||
(compile
|
||||
'(begin
|
||||
(define guardian (make-guardian))
|
||||
(let ((f (lambda () (display "test\n"))))
|
||||
(guardian f))
|
||||
(gc)(gc)(gc)
|
||||
(guardian))))))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue