vm-tables.scm 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. ; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
  2. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  3. ; String hash tables for managing three tables:
  4. ; the symbol table : string -> symbol
  5. ; exported-bindings : string -> shared-binding
  6. ; imported-bindings : string -> shared-binding
  7. ;
  8. ; The hash buckets are linked throught the symbol-next and shared-binding-next
  9. ; fields. The values in the links are converted to fixnums to prevent the GC
  10. ; from tracing them.
  11. ; Size of the hash vectors (is this a reasonable size?).
  12. (define hash-table-slots 1024)
  13. (define hash-table-size (vm-vector-size hash-table-slots))
  14. ; The various hash-table values all have their own link fields.
  15. (define hash-table-entry-size 0)
  16. (define (value->link value)
  17. (assert (not (fixnum? value)))
  18. (if (stob? value)
  19. (descriptor->fixnum value)
  20. value))
  21. (define (link->value link)
  22. (assert (or (false? link)
  23. (fixnum? link)))
  24. (if (fixnum? link)
  25. (fixnum->stob link)
  26. link))
  27. (define (hash-table-ref table i)
  28. (link->value (vm-vector-ref table i)))
  29. (define (hash-table-index string)
  30. (bitwise-and (vm-string-hash string)
  31. (- hash-table-slots 1)))
  32. ; All buckets are initially false.
  33. (define (make-hash-table+gc)
  34. (let ((table (vm-make-vector+gc hash-table-slots)))
  35. (natural-for-each (lambda (index)
  36. (vm-vector-set! table index false))
  37. hash-table-slots)
  38. table))
  39. ; Return a procedure for adding FOO's to tables.
  40. (define (table-adder foo-string set-foo-next!)
  41. (lambda (table foo)
  42. (let ((index (hash-table-index (foo-string foo))))
  43. (set-foo-next! foo (vm-vector-ref table index))
  44. (vm-vector-set! table index (value->link foo)))))
  45. ; Return a function for looking up strings in a Foo table. A new Foo is
  46. ; made if none is found.
  47. (define (table-searcher foo-string foo-next make-foo)
  48. (lambda (table string key)
  49. (let* ((index (hash-table-index string))
  50. (bucket (hash-table-ref table index)))
  51. (let loop ((foo bucket))
  52. (cond ((vm-eq? foo false)
  53. (let ((new (make-foo string (value->link bucket) key)))
  54. (vm-vector-set! table index (value->link new))
  55. new))
  56. ((vm-string=? string (foo-string foo))
  57. foo)
  58. (else
  59. (loop (link->value (foo-next foo)))))))))
  60. ; Same thing, except we remove the entry if it is found.
  61. (define (table-remover foo-string foo-next set-foo-next!)
  62. (lambda (table string)
  63. (let* ((index (hash-table-index string))
  64. (bucket (hash-table-ref table index)))
  65. (let loop ((previous-foo false) (foo bucket))
  66. (cond ((vm-eq? foo false)
  67. (unspecific))
  68. ((not (vm-string=? string (foo-string foo)))
  69. (loop foo (link->value (foo-next foo))))
  70. ((vm-eq? previous-foo false)
  71. (vm-vector-set! table index (foo-next foo)))
  72. (else
  73. (set-foo-next! previous-foo (foo-next foo))))))))
  74. ; Return a procedure that will apply PROC to every element of TABLE.
  75. (define (table-walker foo-next)
  76. (lambda (proc table)
  77. (natural-for-each (lambda (index)
  78. (let loop ((entry (hash-table-ref table index)))
  79. (if (not (vm-eq? entry false))
  80. (begin
  81. (proc entry)
  82. (loop (link->value (foo-next entry)))))))
  83. hash-table-slots)))
  84. ; Return a procedure that will apply PROC to every element of TABLE
  85. ; until PROC returns #f.
  86. (define (table-while-walker foo-next)
  87. (lambda (proc table)
  88. (natural-for-each-while (lambda (index)
  89. (let loop ((entry (hash-table-ref table index)))
  90. (cond
  91. ((vm-eq? entry false) #t)
  92. ((not (proc entry)) #f)
  93. (else
  94. (loop (link->value (foo-next entry)))))))
  95. hash-table-slots)))
  96. ; Copy a table, retaining all entries.
  97. (define (table-tracer foo-next set-foo-next! trace-value)
  98. (make-table-copier trace-value
  99. (entry-tracer foo-next
  100. set-foo-next!
  101. trace-value)))
  102. ; Copy a table, dropping unreferenced entries.
  103. (define (table-cleaner foo-next set-foo-next! extant? trace-value)
  104. (make-table-copier trace-value
  105. (entry-cleaner foo-next
  106. set-foo-next!
  107. extant?
  108. trace-value)))
  109. ; Copy a table.
  110. (define (make-table-copier trace-value entry-tracer)
  111. (lambda (table)
  112. (let ((table (trace-value table)))
  113. (natural-for-each
  114. (lambda (index)
  115. (vm-vector-set! table
  116. index
  117. (entry-tracer (vm-vector-ref table index))))
  118. hash-table-slots)
  119. table)))
  120. ; Loop down a list of foos tracing all of them. We reverse the
  121. ; list in doing so.
  122. (define (entry-tracer foo-next set-foo-next! trace-value)
  123. (lambda (foo-link)
  124. (let loop ((foo-link foo-link) (done-link false))
  125. (let ((foo (link->value foo-link)))
  126. (if (false? foo)
  127. done-link
  128. (let* ((new-foo (trace-value foo))
  129. (next-link (foo-next new-foo)))
  130. (set-foo-next! new-foo done-link)
  131. (loop next-link
  132. (value->link new-foo))))))))
  133. ; Loop down a list of foos removing any untraced ones. We reverse the
  134. ; list in doing so.
  135. (define (entry-cleaner foo-next set-foo-next! extant? trace-value)
  136. (lambda (foo-link)
  137. (let loop ((foo-link foo-link) (okay-link false))
  138. (let ((foo (link->value foo-link)))
  139. (cond ((false? foo)
  140. okay-link)
  141. ((extant? foo)
  142. (let* ((new-foo (trace-value foo))
  143. (next-link (foo-next new-foo)))
  144. (set-foo-next! new-foo okay-link)
  145. (loop next-link
  146. (value->link new-foo))))
  147. (else
  148. (loop (foo-next foo)
  149. okay-link)))))))
  150. (define (relocate-table table relocate foo-next set-foo-next!)
  151. (if (vm-vector? table)
  152. (begin
  153. (natural-for-each
  154. (lambda (index)
  155. (let ((bucket (hash-table-ref table index)))
  156. (if (not (false? bucket))
  157. (let ((bucket (relocate bucket)))
  158. (vm-vector-set! table index (value->link bucket))
  159. (let loop ((entry bucket))
  160. (let ((next (link->value (foo-next entry))))
  161. (if (not (false? next))
  162. (let ((next (relocate next)))
  163. (set-foo-next! entry (value->link next))
  164. (loop next)))))))))
  165. hash-table-slots)
  166. (unspecific))))