traverse.scm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Utility for tracking down storage leaks.
  3. ;
  4. ; Just do (traverse-depth-first obj1) or (traverse-breadth-first obj1),
  5. ; and then (trail obj2) to find out via what path obj1 points to obj2.
  6. ;
  7. ; Breadth first traversal needs misc/queue.scm.
  8. (define *mark-table* #f)
  9. (define *interesting-table* #f)
  10. (define *traverse-count* 0)
  11. (define (start-over)
  12. (set! *mark-table* (make-table hash))
  13. (set! *interesting-table* (make-table))
  14. (set! *traverse-count* 0))
  15. (define (traverse-depth-first obj)
  16. (start-over)
  17. (let recur ((obj obj) (parent (list 'root)) (parent-tag 'root))
  18. (if (stored? obj)
  19. (if (not (table-ref *mark-table* obj))
  20. (let ((tag (visit obj parent parent-tag)))
  21. (for-each-subobject (lambda (child)
  22. (recur child obj tag))
  23. obj))))))
  24. (define (traverse-breadth-first obj)
  25. (start-over)
  26. (let ((queue (make-queue)))
  27. (define (deal-with obj parent parent-tag)
  28. (if (stored? obj)
  29. (if (not (table-ref *mark-table* obj))
  30. (enqueue! queue
  31. (cons obj
  32. (visit obj parent parent-tag))))))
  33. (deal-with obj (list 'root) 'root)
  34. (let loop ()
  35. (if (not (queue-empty? queue))
  36. (let* ((parent+tag (dequeue! queue))
  37. (parent (car parent+tag))
  38. (parent-tag (cdr parent+tag)))
  39. (for-each-subobject (lambda (obj)
  40. (deal-with obj parent parent-tag))
  41. parent)
  42. (loop))))))
  43. (define (visit obj parent parent-tag)
  44. (table-set! *mark-table* obj parent)
  45. (if (interesting? obj)
  46. (let ((tag *traverse-count*))
  47. (table-set! *interesting-table* tag obj)
  48. (set! *traverse-count* (+ *traverse-count* 1))
  49. (write tag) (display " ")
  50. (write (list parent-tag))
  51. (display ": ") (write obj) (newline)
  52. tag)
  53. parent-tag))
  54. (define (trail obj)
  55. (let loop ((obj (if (integer? obj)
  56. (table-ref *interesting-table* obj)
  57. obj)))
  58. (let ((probe (table-ref *mark-table* obj)))
  59. (if probe
  60. (loop probe))
  61. (if (not (vector? obj))
  62. (begin (write obj)
  63. (newline))))))
  64. (define (interesting? obj)
  65. (and (closure? obj)
  66. (let ((info (template-info (closure-template obj))))
  67. (if (integer? info)
  68. (> info first-interesting-template-info)
  69. #t))))
  70. (define (template-info tem) (template-ref tem 1))
  71. (define first-interesting-template-info
  72. (template-info
  73. (closure-template
  74. (loophole :closure read)))) ;foo
  75. ;(define (interesting? obj)
  76. ; (if (pair? obj)
  77. ; #f
  78. ; (if (vector? obj)
  79. ; #f
  80. ; #t)))
  81. (define (for-each-subobject proc obj)
  82. (cond ((pair? obj)
  83. (proc (car obj))
  84. (proc (cdr obj)))
  85. ((symbol? obj)
  86. (proc (symbol->string obj)))
  87. ((vector? obj)
  88. (vector-for-each proc obj))
  89. ((closure? obj)
  90. (proc (closure-template obj))
  91. (proc (closure-env obj)))
  92. ((location? obj)
  93. (proc (location-id obj))
  94. (if (location-defined? obj)
  95. (proc (contents obj))))
  96. ((record? obj)
  97. (cond ((eq? obj *mark-table*) ;or (debug-data-table)
  98. (display "skipping mark table") (newline))
  99. ((eq? obj *interesting-table*)
  100. (display "skipping interesting table") (newline))
  101. (else
  102. (record-for-each proc obj))))
  103. ((continuation? obj)
  104. (continuation-for-each proc obj))
  105. ((template? obj)
  106. (template-for-each proc obj))
  107. ((extended-number? obj)
  108. (extended-number-for-each proc obj))))
  109. (define (vector-for-each proc v)
  110. (let ((z (vector-length v)))
  111. (do ((i (- z 1) (- i 1)))
  112. ((< i 0) #f)
  113. (if (not (vector-unassigned? v i))
  114. (proc (vector-ref v i))))))
  115. (define-syntax define-for-each
  116. (syntax-rules ()
  117. ((define-for-each foo-for-each foo-length foo-ref)
  118. (define (foo-for-each proc v)
  119. (let ((z (foo-length v)))
  120. (do ((i (- z 1) (- i 1)))
  121. ((< i 0) #f)
  122. (proc (foo-ref v i))))))))
  123. (define-for-each record-for-each
  124. record-length record-ref)
  125. (define-for-each continuation-for-each
  126. continuation-length continuation-ref)
  127. (define-for-each template-for-each
  128. template-length template-ref)
  129. (define-for-each extended-number-for-each
  130. extended-number-length extended-number-ref)
  131. (define (quick-hash obj n)
  132. (cond ((symbol? obj) (string-hash (symbol->string obj)))
  133. ((location? obj) (+ 3 (quick-hash (location-id obj) n)))
  134. ((string? obj) (+ 33 (string-hash obj)))
  135. ((integer? obj) (if (and (>= obj 0)
  136. (< obj hash-mask))
  137. obj
  138. (modulo obj hash-mask)))
  139. ((char? obj) (+ 333 (char->integer obj)))
  140. ((eq? obj #f) 3001)
  141. ((eq? obj #t) 3003)
  142. ((null? obj) 3005)
  143. ((pair? obj) (if (= n 0)
  144. 30007
  145. (+ (quick-hash (car obj) (- n 1))
  146. (quick-hash (cdr obj) (- n 1)))))
  147. ((vector? obj) (if (= n 0)
  148. 30009
  149. (if (> (vector-length obj) 1)
  150. (+ 30011 (quick-hash (vector-ref obj 1)
  151. (- n 1)))
  152. 30017)))
  153. ((number? obj) 4000)
  154. ((closure? obj) 4004)
  155. ((template? obj) (if (= n 0)
  156. 300013
  157. (+ 30027 (quick-hash (template-ref obj 1)
  158. (- n 1)))))
  159. ((output-port? obj) 4006)
  160. ((input-port? obj) 4007)
  161. ((record? obj) 4008)
  162. ((continuation? obj) 4009)
  163. ((number? obj) 40010)
  164. ((string? obj) 40011)
  165. ((code-vector? obj) 40012)
  166. ((eq? obj (unspecific)) 40013)
  167. (else 50007)))
  168. (define hash-mask (- (arithmetic-shift 1 26) 1))
  169. (define (hash obj) (quick-hash obj 1))
  170. (define (leaf? obj)
  171. (or (and (number? obj)
  172. (not (extended-number? obj)))
  173. ;; (symbol? obj)
  174. (string? obj)
  175. (code-vector? obj)
  176. (char? obj)
  177. (eq? obj #f)
  178. (eq? obj #t)
  179. (eq? obj '())
  180. (eq? obj (unspecific))))
  181. (define usual-leaf-predicate leaf?)
  182. (define (set-leaf-predicate! proc) (set! leaf? proc))
  183. (define (stored? obj) (not (leaf? obj)))
  184. (define least-fixnum (arithmetic-shift -1 29))
  185. (define greatest-fixnum (- -1 least-fixnum))