/src/gc.lisp

https://github.com/mathematical-systems/manardb · Lisp · 130 lines · 122 code · 7 blank · 1 comment · 22 complexity · 9ee2e3e2ec6e51ce15413b141c17a872 MD5 · raw file

  1. (in-package #:manardb)
  2. (defun gc-compact (offsets-table)
  3. (loop for mtagmap across *mtagmaps*
  4. for offsets across offsets-table
  5. for tag from 0
  6. when offsets
  7. do
  8. (let ((elem-len (mtagmap-elem-len mtagmap)) (cur-offset (mtagmap-first-index mtagmap)))
  9. (loop for new-offset across offsets
  10. for old-offset from (mtagmap-first-index mtagmap) by elem-len
  11. do
  12. (unless (zerop new-offset)
  13. (assert (= cur-offset new-offset))
  14. (assert (>= old-offset new-offset))
  15. (osicat-posix:memmove (mpointer tag new-offset) (mpointer tag old-offset) elem-len)
  16. (setf cur-offset (+ new-offset elem-len))))
  17. (setf (mtagmap-next mtagmap) cur-offset))))
  18. (defun gc-calc-new-offsets (mtagmap table)
  19. (when table
  20. (let ((offsets (make-array (length table) :element-type 'mindex :initial-element 0))
  21. (next (mtagmap-first-index mtagmap))
  22. (elem-len (mtagmap-elem-len mtagmap)))
  23. (loop for refs across table
  24. for i from 0
  25. do (when refs
  26. (setf (aref offsets i) next)
  27. (incf next elem-len)))
  28. offsets)))
  29. (defun gc-rewrite-pointers-and-compact (refs-table)
  30. (clear-caches)
  31. (let ((offsets-table (map 'vector 'gc-calc-new-offsets *mtagmaps* refs-table)))
  32. (loop for mtagmap across *mtagmaps*
  33. for tag from 0
  34. for elem-len = (when mtagmap (mtagmap-elem-len mtagmap))
  35. for table across refs-table
  36. for offsets across offsets-table
  37. when table
  38. do
  39. (mtagmap-check mtagmap)
  40. (loop for pos from 0
  41. for refs across table
  42. for old-offset from (mtagmap-first-index mtagmap) by elem-len
  43. for old-mptr = (make-mptr tag old-offset)
  44. for new-offset across offsets
  45. for new-mptr = (make-mptr tag new-offset)
  46. when refs
  47. do
  48. (labels ((up (ref)
  49. (declare (type mptr ref))
  50. (unless (zerop ref)
  51. (assert (= (d (mptr-pointer ref) 0 mptr) old-mptr))
  52. (unless (= old-mptr new-mptr)
  53. (setf (d (mptr-pointer ref) 0 mptr) new-mptr))))) ;;; XXX only write if necessary so that pages are not pointlessly dirtied
  54. (typecase refs
  55. (array
  56. (loop for r across refs do (up r)))
  57. (t
  58. (up refs))))))
  59. (gc-compact offsets-table)))
  60. (defun gc (root-objects-sequence &key verbose (collect-and-compact t))
  61. "Do a full and precise garbage collection over all objects in the memory mapped system.
  62. If COLLECT-AND-COMPACT is true, then unused objeccts are removed.
  63. Uses at least two pointers of Lisp memory per object and more if
  64. objects are densely referenced. See REWRITE-GC for a sloppier
  65. alternative that does not need so much memory.
  66. "
  67. (declare (optimize speed))
  68. (let ((refs-table (map 'vector (lambda (m)
  69. (unless (or (not m) (mtagmap-closed-p m))
  70. ;;; also tried with a hash-table but in comparison it is very very slow on Allegro
  71. (make-array (mtagmap-count m) :initial-element nil)))
  72. *mtagmaps*))
  73. (root-objects-sequence (map '(vector mptr) #'force-mptr root-objects-sequence )))
  74. (macrolet ((r (mptr)
  75. (check-type mptr symbol)
  76. `(aref (aref refs-table (mptr-tag ,mptr)) (mtagmap-elem-pos (mtagmap (mptr-tag ,mptr)) (mptr-index ,mptr)) )
  77. ))
  78. (labels ((add-ref (mptr referrer)
  79. (symbol-macrolet ((ref (r mptr)))
  80. (let ((rref ref))
  81. (typecase rref
  82. (array
  83. (when (zerop referrer)
  84. (return-from add-ref))
  85. (vector-push-extend referrer rref))
  86. (null
  87. (setf ref referrer))
  88. (t
  89. (cond ((zerop rref)
  90. (setf ref referrer))
  91. ((= rref referrer))
  92. (t
  93. (setf ref
  94. (make-array 2 :adjustable t :fill-pointer 2
  95. :initial-contents (list rref referrer)
  96. :element-type 'mptr)))))))))
  97. (walk-ref (mptr referrer len)
  98. (unless (zerop mptr)
  99. (let ((first-time (not (r mptr))))
  100. (add-ref mptr referrer)
  101. (when first-time
  102. (let ((walker (mtagmap-walker (mtagmap (mptr-tag mptr)))))
  103. (when walker
  104. (funcall walker mptr #'walk-ref))))
  105. (unless (= 1 len)
  106. (walk-ref (+ mptr (ash (mtagmap-elem-len
  107. (mtagmap (mptr-tag mptr))) +mtag-bits+)) 0 (1- len)))))))
  108. (declare (dynamic-extent #'walk-ref #'add-ref))
  109. (iter (for o in-vector root-objects-sequence)
  110. (walk-ref o 0 1))
  111. (when verbose
  112. (loop for m across *mtagmaps*
  113. for table across refs-table
  114. do
  115. (when table
  116. (format t "~A total ~D used ~D~&"
  117. (mtagmap-class m) (mtagmap-count m)
  118. (count-if-not #'not table)
  119. ))))
  120. (when collect-and-compact
  121. (gc-rewrite-pointers-and-compact refs-table)
  122. (shrink-all-mmaps))
  123. (values)))))