123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
- ; Utility for tracking down storage leaks.
- ;
- ; Just do (traverse-depth-first obj1) or (traverse-breadth-first obj1),
- ; and then (trail obj2) to find out via what path obj1 points to obj2.
- ;
- ; Breadth first traversal needs misc/queue.scm.
- (define *mark-table* #f)
- (define *interesting-table* #f)
- (define *traverse-count* 0)
- (define (start-over)
- (set! *mark-table* (make-table hash))
- (set! *interesting-table* (make-table))
- (set! *traverse-count* 0))
- (define (traverse-depth-first obj)
- (start-over)
- (let recur ((obj obj) (parent (list 'root)) (parent-tag 'root))
- (if (stored? obj)
- (if (not (table-ref *mark-table* obj))
- (let ((tag (visit obj parent parent-tag)))
- (for-each-subobject (lambda (child)
- (recur child obj tag))
- obj))))))
- (define (traverse-breadth-first obj)
- (start-over)
- (let ((queue (make-queue)))
- (define (deal-with obj parent parent-tag)
- (if (stored? obj)
- (if (not (table-ref *mark-table* obj))
- (enqueue! queue
- (cons obj
- (visit obj parent parent-tag))))))
- (deal-with obj (list 'root) 'root)
- (let loop ()
- (if (not (queue-empty? queue))
- (let* ((parent+tag (dequeue! queue))
- (parent (car parent+tag))
- (parent-tag (cdr parent+tag)))
- (for-each-subobject (lambda (obj)
- (deal-with obj parent parent-tag))
- parent)
- (loop))))))
- (define (visit obj parent parent-tag)
- (table-set! *mark-table* obj parent)
- (if (interesting? obj)
- (let ((tag *traverse-count*))
- (table-set! *interesting-table* tag obj)
- (set! *traverse-count* (+ *traverse-count* 1))
- (write tag) (display " ")
- (write (list parent-tag))
- (display ": ") (write obj) (newline)
- tag)
- parent-tag))
- (define (trail obj)
- (let loop ((obj (if (integer? obj)
- (table-ref *interesting-table* obj)
- obj)))
- (let ((probe (table-ref *mark-table* obj)))
- (if probe
- (loop probe))
- (if (not (vector? obj))
- (begin (write obj)
- (newline))))))
- (define (interesting? obj)
- (and (closure? obj)
- (let ((info (template-info (closure-template obj))))
- (if (integer? info)
- (> info first-interesting-template-info)
- #t))))
- (define (template-info tem) (template-ref tem 1))
- (define first-interesting-template-info
- (template-info
- (closure-template
- (loophole :closure read)))) ;foo
-
- ;(define (interesting? obj)
- ; (if (pair? obj)
- ; #f
- ; (if (vector? obj)
- ; #f
- ; #t)))
-
- (define (for-each-subobject proc obj)
- (cond ((pair? obj)
- (proc (car obj))
- (proc (cdr obj)))
- ((symbol? obj)
- (proc (symbol->string obj)))
- ((vector? obj)
- (vector-for-each proc obj))
- ((closure? obj)
- (proc (closure-template obj))
- (proc (closure-env obj)))
- ((location? obj)
- (proc (location-id obj))
- (if (location-defined? obj)
- (proc (contents obj))))
- ((record? obj)
- (cond ((eq? obj *mark-table*) ;or (debug-data-table)
- (display "skipping mark table") (newline))
- ((eq? obj *interesting-table*)
- (display "skipping interesting table") (newline))
- (else
- (record-for-each proc obj))))
- ((continuation? obj)
- (continuation-for-each proc obj))
- ((template? obj)
- (template-for-each proc obj))
- ((extended-number? obj)
- (extended-number-for-each proc obj))))
- (define (vector-for-each proc v)
- (let ((z (vector-length v)))
- (do ((i (- z 1) (- i 1)))
- ((< i 0) #f)
- (if (not (vector-unassigned? v i))
- (proc (vector-ref v i))))))
- (define-syntax define-for-each
- (syntax-rules ()
- ((define-for-each foo-for-each foo-length foo-ref)
- (define (foo-for-each proc v)
- (let ((z (foo-length v)))
- (do ((i (- z 1) (- i 1)))
- ((< i 0) #f)
- (proc (foo-ref v i))))))))
- (define-for-each record-for-each
- record-length record-ref)
- (define-for-each continuation-for-each
- continuation-length continuation-ref)
- (define-for-each template-for-each
- template-length template-ref)
- (define-for-each extended-number-for-each
- extended-number-length extended-number-ref)
- (define (quick-hash obj n)
- (cond ((symbol? obj) (string-hash (symbol->string obj)))
- ((location? obj) (+ 3 (quick-hash (location-id obj) n)))
- ((string? obj) (+ 33 (string-hash obj)))
- ((integer? obj) (if (and (>= obj 0)
- (< obj hash-mask))
- obj
- (modulo obj hash-mask)))
- ((char? obj) (+ 333 (char->integer obj)))
- ((eq? obj #f) 3001)
- ((eq? obj #t) 3003)
- ((null? obj) 3005)
- ((pair? obj) (if (= n 0)
- 30007
- (+ (quick-hash (car obj) (- n 1))
- (quick-hash (cdr obj) (- n 1)))))
- ((vector? obj) (if (= n 0)
- 30009
- (if (> (vector-length obj) 1)
- (+ 30011 (quick-hash (vector-ref obj 1)
- (- n 1)))
- 30017)))
- ((number? obj) 4000)
- ((closure? obj) 4004)
- ((template? obj) (if (= n 0)
- 300013
- (+ 30027 (quick-hash (template-ref obj 1)
- (- n 1)))))
- ((output-port? obj) 4006)
- ((input-port? obj) 4007)
- ((record? obj) 4008)
- ((continuation? obj) 4009)
- ((number? obj) 40010)
- ((string? obj) 40011)
- ((code-vector? obj) 40012)
- ((eq? obj (unspecific)) 40013)
- (else 50007)))
- (define hash-mask (- (arithmetic-shift 1 26) 1))
- (define (hash obj) (quick-hash obj 1))
- (define (leaf? obj)
- (or (and (number? obj)
- (not (extended-number? obj)))
- ;; (symbol? obj)
- (string? obj)
- (code-vector? obj)
- (char? obj)
- (eq? obj #f)
- (eq? obj #t)
- (eq? obj '())
- (eq? obj (unspecific))))
- (define usual-leaf-predicate leaf?)
- (define (set-leaf-predicate! proc) (set! leaf? proc))
- (define (stored? obj) (not (leaf? obj)))
- (define least-fixnum (arithmetic-shift -1 29))
- (define greatest-fixnum (- -1 least-fixnum))
|