/collects/tests/plai/gc/good-collectors/good-collector.rkt

http://github.com/gmarceau/PLT · Racket · 274 lines · 3 code · 3 blank · 268 comment · 0 complexity · 7dc234b8e46b26d4f81743e30e8606dd MD5 · raw file

  1. #lang plai/collector
  2. #|
  3. A collector for use in testing the random mutator generator.
  4. |#
  5. (print-only-errors #t)
  6. (define (find-free-space start size)
  7. (cond
  8. [(= start (heap-size))
  9. #f]
  10. [(n-free-blocks? start size)
  11. start]
  12. [else
  13. (find-free-space (+ start 1) size)]))
  14. (define (n-free-blocks? start size)
  15. (cond
  16. [(= size 0) #t]
  17. [(= start (heap-size)) #f]
  18. [else
  19. (and (eq? 'free (heap-ref start))
  20. (n-free-blocks? (+ start 1) (- size 1)))]))
  21. (test (with-heap #(free free free)
  22. (n-free-blocks? 0 2))
  23. #t)
  24. (test (with-heap #(free free free)
  25. (n-free-blocks? 0 3))
  26. #t)
  27. (test (with-heap #(free free free)
  28. (n-free-blocks? 0 4))
  29. #f)
  30. (test (with-heap #(free free free)
  31. (n-free-blocks? 2 1))
  32. #t)
  33. (test (with-heap #(free free free)
  34. (n-free-blocks? 2 2))
  35. #f)
  36. (test (with-heap #(free free free)
  37. (find-free-space 0 1))
  38. 0)
  39. (test (with-heap #(pair free free)
  40. (find-free-space 0 1))
  41. 1)
  42. (test (with-heap #(pair free free)
  43. (find-free-space 0 2))
  44. 1)
  45. (test (with-heap #(pair free free)
  46. (find-free-space 0 3))
  47. #f)
  48. (define (init-allocator)
  49. (for ([i (in-range 0 (heap-size))])
  50. (heap-set! i 'free)))
  51. (test (let ([v (make-vector 12 'x)])
  52. (with-heap v (init-allocator))
  53. v)
  54. (make-vector 12 'free))
  55. (define (gc:deref loc)
  56. (cond
  57. [(equal? (heap-ref loc) 'flat)
  58. (heap-ref (+ loc 1))]
  59. [else
  60. (error 'gc:deref "attempted to deref a non flat value, loc ~s" loc)]))
  61. (test (with-heap (vector 'free 'free 'free 'flat 14 'free 'free)
  62. (gc:deref 3))
  63. 14)
  64. (define (gc:first pr-ptr)
  65. (if (equal? (heap-ref pr-ptr) 'pair)
  66. (heap-ref (+ pr-ptr 1))
  67. (error 'first "non pair")))
  68. (test (with-heap (vector 'free 'flat 3 'pair 0 1)
  69. (gc:first 3))
  70. 0)
  71. (define (gc:rest pr-ptr)
  72. (if (equal? (heap-ref pr-ptr) 'pair)
  73. (heap-ref (+ pr-ptr 2))
  74. (error 'first "non pair")))
  75. (test (with-heap (vector 'free 'flat 3 'pair 0 1)
  76. (gc:rest 3))
  77. 1)
  78. (define (gc:flat? loc) (equal? (heap-ref loc) 'flat))
  79. (test (with-heap (vector 'free 'free 'pair 0 1 'flat 14)
  80. (gc:flat? 2))
  81. #f)
  82. (test (with-heap (vector 'free 'free 'pair 0 1 'flat 14)
  83. (gc:flat? 5))
  84. #t)
  85. (define (gc:cons? loc) (equal? (heap-ref loc) 'pair))
  86. (test (with-heap (vector 'free 'free 'pair 0 1 'flat 14)
  87. (gc:cons? 2))
  88. #t)
  89. (test (with-heap (vector 'free 'free 'pair 0 1 'flat 14)
  90. (gc:cons? 5))
  91. #f)
  92. (define (gc:set-first! pr-ptr new)
  93. (if (equal? (heap-ref pr-ptr) 'pair)
  94. (heap-set! (+ pr-ptr 1) new)
  95. (error 'set-first! "non pair")))
  96. (define (gc:set-rest! pr-ptr new)
  97. (if (equal? (heap-ref pr-ptr) 'pair)
  98. (heap-set! (+ pr-ptr 2) new)
  99. (error 'set-first! "non pair")))
  100. (define (gc:alloc-flat fv)
  101. (let ([ptr (alloc 2 (Îť ()
  102. (if (procedure? fv)
  103. (append (procedure-roots fv)
  104. (get-root-set))
  105. (get-root-set))))])
  106. (heap-set! ptr 'flat)
  107. (heap-set! (+ ptr 1) fv)
  108. ptr))
  109. (define (gc:cons hd tl)
  110. (let ([ptr (alloc 3 (Îť () (get-root-set hd tl)))])
  111. (heap-set! ptr 'pair)
  112. (heap-set! (+ ptr 1) hd)
  113. (heap-set! (+ ptr 2) tl)
  114. ptr))
  115. (define (alloc n get-roots)
  116. (let ([next (find-free-space 0 n)])
  117. (cond
  118. [next
  119. next]
  120. [else
  121. (collect-garbage get-roots)
  122. (let ([next (find-free-space 0 n)])
  123. (unless next
  124. (error 'alloc "out of space"))
  125. next)])))
  126. (define (collect-garbage get-roots)
  127. (let ([roots (map read-root (get-roots))])
  128. (collect-garbage-help roots
  129. (remove* roots (get-all-records 0)))))
  130. (define (collect-garbage-help gray white)
  131. (cond
  132. [(null? gray) (free! white)]
  133. [else
  134. (case (heap-ref (car gray))
  135. [(flat)
  136. (let ([proc (heap-ref (+ (car gray) 1))])
  137. (if (procedure? proc)
  138. (let ([new-locs (map read-root (procedure-roots proc))])
  139. (collect-garbage-help
  140. (add-in new-locs (cdr gray) white)
  141. (remove* new-locs white)))
  142. (collect-garbage-help (cdr gray) white)))]
  143. [(pair)
  144. (let ([hd (heap-ref (+ (car gray) 1))]
  145. [tl (heap-ref (+ (car gray) 2))])
  146. (collect-garbage-help
  147. (add-in (list hd tl) (cdr gray) white)
  148. (remove tl (remove hd white))))]
  149. [else
  150. (error 'collect-garbage "unknown tag ~s, loc ~s" (heap-ref (car gray)) (car gray))])]))
  151. (define (free! whites)
  152. (cond
  153. [(null? whites) (void)]
  154. [else
  155. (let ([white (car whites)])
  156. (case (heap-ref white)
  157. [(pair)
  158. (heap-set! white 'free)
  159. (heap-set! (+ white 1) 'free)
  160. (heap-set! (+ white 2) 'free)]
  161. [(flat)
  162. (heap-set! white 'free)
  163. (heap-set! (+ white 1) 'free)]
  164. [else
  165. (error 'free! "unknown tag ~s\n" (heap-ref white))])
  166. (free! (cdr whites)))]))
  167. (test (let ([v (vector #f #t '() 0 1 2 3 4 5 6 'pair 0 1 'flat 14 'pair 0 1 'flat 12)])
  168. (with-heap v (free! (list 10 18)))
  169. v)
  170. (vector #f #t '() 0 1 2 3 4 5 6 'free 'free 'free 'flat 14 'pair 0 1 'free 'free))
  171. ;; add-in : (listof location) (listof location) (listof location) -> (listof location)
  172. ;; computes a new set of gray addresses by addding all white elements of locs to gray
  173. (define (add-in locs gray white)
  174. (cond
  175. [(null? locs) gray]
  176. [else
  177. (let* ([loc (car locs)]
  178. [white? (member loc white)])
  179. (add-in (cdr locs)
  180. (if white? (cons loc gray) gray)
  181. white))]))
  182. (test (add-in '(13 14) '(100 102) '(13 14 104 105))
  183. '(14 13 100 102))
  184. (test (add-in '(13 14) '(100 102) '(13 104 105))
  185. '(13 100 102))
  186. (define (get-all-records i)
  187. (cond
  188. [(< i (heap-size))
  189. (case (heap-ref i)
  190. [(pair) (cons i (get-all-records (+ i 3)))]
  191. [(flat) (cons i (get-all-records (+ i 2)))]
  192. [(free) (get-all-records (+ i 1))]
  193. [else (get-all-records (+ i 1))])]
  194. [else null]))
  195. (test (with-heap (vector #f #t '() 0 1 2 3 4 5 6 'pair 0 1 'flat 14 'pair 0 1 'flat 12)
  196. (get-all-records 0))
  197. (list 10 13 15 18))
  198. (test (with-heap (make-vector 10 'free) (gc:alloc-flat #f))
  199. 0)
  200. (test (with-heap (make-vector 10 'free) (gc:alloc-flat #t) (gc:alloc-flat #f))
  201. 2)
  202. (test (let ([v (vector 'flat 0 'flat 1)])
  203. (with-heap v (collect-garbage-help (list)
  204. (get-all-records 0)))
  205. v)
  206. (vector 'free 'free 'free 'free))
  207. (test (let ([v (vector 'flat 0 'flat 1)])
  208. (with-heap v (collect-garbage-help (list 0)
  209. (remove 0 (get-all-records 0))))
  210. v)
  211. (vector 'flat 0 'free 'free))
  212. (test (let ([v (vector 'flat 0 'flat 1)])
  213. (with-heap v (collect-garbage-help (list 2)
  214. (remove 2 (get-all-records 0))))
  215. v)
  216. (vector 'free 'free 'flat 1))
  217. (test (let ([v (vector 'flat 0 'flat 1 'pair 0 2)])
  218. (with-heap v (collect-garbage-help (list 4)
  219. (remove 4 (get-all-records 0))))
  220. v)
  221. (vector 'flat 0 'flat 1 'pair 0 2))
  222. (test (let ([v (vector 'flat 0 'flat 1 'pair 0 0)])
  223. (with-heap v (collect-garbage-help (list 4)
  224. (remove 4 (get-all-records 0))))
  225. v)
  226. (vector 'flat 0 'free 'free 'pair 0 0))
  227. (test (let ([v (vector 'flat 0 'flat 1 'pair 4 4)])
  228. (with-heap v (collect-garbage-help (list 4)
  229. (remove 4 (get-all-records 0))))
  230. v)
  231. (vector 'free 'free 'free 'free 'pair 4 4))