traverse.scm 5.6 KB

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