0.6.12.11:
[sbcl.git] / src / code / target-hash-table.lisp
1 ;;;; that part of the implementation of HASH-TABLE which lives solely
2 ;;;; on the target system, not on the cross-compilation host
3
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
12
13 (in-package "SB!IMPL")
14 \f
15 ;;;; utilities
16
17 (eval-when (:compile-toplevel :load-toplevel :execute)
18   (defconstant max-hash most-positive-fixnum))
19
20 (deftype hash ()
21   `(integer 0 ,max-hash))
22
23 ;;; FIXME: Does this always make a nonnegative FIXNUM? If so, then
24 ;;; explain why. If not (or if the reason it always makes a
25 ;;; nonnegative FIXNUM is only the accident that pointers in supported
26 ;;; architectures happen to be in the lower half of the address
27 ;;; space), then fix it.
28 #!-sb-fluid (declaim (inline pointer-hash))
29 (defun pointer-hash (key)
30   (declare (values hash))
31   (truly-the hash (%primitive sb!c:make-fixnum key)))
32
33 #!-sb-fluid (declaim (inline eq-hash))
34 (defun eq-hash (key)
35   (declare (values hash (member t nil)))
36   (values (pointer-hash key)
37           (oddp (get-lisp-obj-address key))))
38
39 #!-sb-fluid (declaim (inline equal-hash))
40 (defun equal-hash (key)
41   (declare (values hash (member t nil)))
42   (values (sxhash key) nil))
43
44 #!-sb-fluid (declaim (inline eql-hash))
45 (defun eql-hash (key)
46   (declare (values hash (member t nil)))
47   (if (numberp key)
48       (equal-hash key)
49       (eq-hash key)))
50
51 (defun equalp-hash (key)
52   (declare (values hash (member t nil)))
53   (values (psxhash key) nil))
54
55 (defun almost-primify (num)
56   (declare (type index num))
57   #!+sb-doc
58   "Return an almost prime number greater than or equal to NUM."
59   (if (= (rem num 2) 0)
60       (setq num (+ 1 num)))
61   (if (= (rem num 3) 0)
62       (setq num (+ 2 num)))
63   (if (= (rem num 7) 0)
64       (setq num (+ 4 num)))
65   num)
66 \f
67 ;;;; user-defined hash table tests
68
69 (defvar *hash-table-tests* nil)
70
71 (defun define-hash-table-test (name test-fun hash-fun)
72   #!+sb-doc
73   "Define a new kind of hash table test."
74   (declare (type symbol name)
75            (type function test-fun hash-fun))
76   (setf *hash-table-tests*
77         (cons (list name test-fun hash-fun)
78               (remove name *hash-table-tests* :test #'eq :key #'car)))
79   name)
80 \f
81 ;;;; construction and simple accessors
82
83 (defconstant +min-hash-table-size+ 16)
84
85 (defun make-hash-table (&key (test 'eql)
86                              (size +min-hash-table-size+)
87                              (rehash-size 1.5)
88                              (rehash-threshold 1)
89                              (weak-p nil))
90   #!+sb-doc
91   "Create and return a new hash table. The keywords are as follows:
92      :TEST -- Indicates what kind of test to use.
93      :SIZE -- A hint as to how many elements will be put in this hash
94        table.
95      :REHASH-SIZE -- Indicates how to expand the table when it fills up.
96        If an integer, add space for that many elements. If a floating
97        point number (which must be greater than 1.0), multiply the size
98        by that amount.
99      :REHASH-THRESHOLD -- Indicates how dense the table can become before
100        forcing a rehash. Can be any positive number <=1, with density
101        approaching zero as the threshold approaches 0. Density 1 means an
102        average of one entry per bucket.
103      :WEAK-P -- (This is an extension from CMU CL, not currently supported
104        in SBCL 0.6.6, but perhaps supported in a future version.) If T,
105        don't keep entries if the key would otherwise be garbage."
106   (declare (type (or function symbol) test))
107   (declare (type unsigned-byte size))
108   (when weak-p
109     (error "stub: unsupported WEAK-P option"))
110   (multiple-value-bind (test test-fun hash-fun)
111       (cond ((or (eq test #'eq) (eq test 'eq))
112              (values 'eq #'eq #'eq-hash))
113             ((or (eq test #'eql) (eq test 'eql))
114              (values 'eql #'eql #'eql-hash))
115             ((or (eq test #'equal) (eq test 'equal))
116              (values 'equal #'equal #'equal-hash))
117             ((or (eq test #'equalp) (eq test 'equalp))
118              (values 'equalp #'equalp #'equalp-hash))
119             (t
120              ;; FIXME: I'd like to remove *HASH-TABLE-TESTS* stuff.
121              ;; Failing that, I'd like to rename it to
122              ;; *USER-HASH-TABLE-TESTS*.
123              (dolist (info *hash-table-tests*
124                            (error "unknown :TEST for MAKE-HASH-TABLE: ~S"
125                                   test))
126                (destructuring-bind (test-name test-fun hash-fun) info
127                  (when (or (eq test test-name) (eq test test-fun))
128                    (return (values test-name test-fun hash-fun)))))))
129     (let* ((size (max +min-hash-table-size+
130                       (min size
131                            ;; SIZE is just a hint, so if the user asks
132                            ;; for a SIZE which'd be too big for us to
133                            ;; easily implement, we bump it down.
134                            (floor array-dimension-limit 16))))
135            (rehash-size (if (integerp rehash-size)
136                             rehash-size
137                             (float rehash-size 1.0)))
138            ;; FIXME: Original REHASH-THRESHOLD default should be 1.0,
139            ;; not 1, to make it easier for the compiler to avoid
140            ;; boxing.
141            (rehash-threshold (float rehash-threshold 1.0))
142            (size+1 (1+ size))           ; The first element is not usable.
143            (scaled-size (round (/ (float size+1) rehash-threshold)))
144            (length (almost-primify (max scaled-size
145                                         (1+ +min-hash-table-size+))))
146            (index-vector (make-array length
147                                      :element-type '(unsigned-byte 32)
148                                      :initial-element 0))
149            ;; needs to be the same length as the KV vector
150            (next-vector (make-array size+1
151                                     :element-type '(unsigned-byte 32)))
152            (kv-vector (make-array (* 2 size+1)
153                                   :initial-element +empty-ht-slot+))
154            (table (%make-hash-table
155                    :test test
156                    :test-fun test-fun
157                    :hash-fun hash-fun
158                    :rehash-size rehash-size
159                    :rehash-threshold rehash-threshold
160                    :rehash-trigger size
161                    :table kv-vector
162                    :weak-p weak-p
163                    :index-vector index-vector
164                    :next-vector next-vector
165                    :hash-vector (unless (eq test 'eq)
166                                   (make-array size+1
167                                               :element-type '(unsigned-byte 32)
168                                               :initial-element #x80000000)))))
169       (declare (type index size+1 scaled-size length))
170       ;; Set up the free list, all free. These lists are 0 terminated.
171       (do ((i 1 (1+ i)))
172           ((>= i size))
173         (setf (aref next-vector i) (1+ i)))
174       (setf (aref next-vector size) 0)
175       (setf (hash-table-next-free-kv table) 1)
176       (setf (hash-table-needing-rehash table) 0)
177       (setf (aref kv-vector 0) table)
178       table)))
179
180 (defun hash-table-count (hash-table)
181   #!+sb-doc
182   "Returns the number of entries in the given HASH-TABLE."
183   (declare (type hash-table hash-table)
184            (values index))
185   (hash-table-number-entries hash-table))
186
187 #!+sb-doc
188 (setf (fdocumentation 'hash-table-rehash-size 'function)
189       "Return the rehash-size HASH-TABLE was created with.")
190
191 #!+sb-doc
192 (setf (fdocumentation 'hash-table-rehash-threshold 'function)
193       "Return the rehash-threshold HASH-TABLE was created with.")
194
195 (defun hash-table-size (hash-table)
196   #!+sb-doc
197   "Return a size that can be used with MAKE-HASH-TABLE to create a hash
198    table that can hold however many entries HASH-TABLE can hold without
199    having to be grown."
200   (hash-table-rehash-trigger hash-table))
201
202 #!+sb-doc
203 (setf (fdocumentation 'hash-table-test 'function)
204       "Return the test HASH-TABLE was created with.")
205
206 #!+sb-doc
207 (setf (fdocumentation 'hash-table-weak-p 'function)
208       "Return T if HASH-TABLE will not keep entries for keys that would
209    otherwise be garbage, and NIL if it will.")
210 \f
211 ;;;; accessing functions
212
213 ;;; Make new vectors for the table, extending the table based on the
214 ;;; rehash-size.
215 (defun rehash (table)
216   (declare (type hash-table table))
217   (let* ((old-kv-vector (hash-table-table table))
218          (old-next-vector (hash-table-next-vector table))
219          (old-hash-vector (hash-table-hash-vector table))
220          (old-size (length old-next-vector))
221          (new-size
222           (let ((rehash-size (hash-table-rehash-size table)))
223             (etypecase rehash-size
224               (fixnum
225                (+ rehash-size old-size))
226               (float
227                (the index (round (* rehash-size old-size)))))))
228          (new-kv-vector (make-array (* 2 new-size)
229                                     :initial-element +empty-ht-slot+))
230          (new-next-vector (make-array new-size
231                                       :element-type '(unsigned-byte 32)
232                                       :initial-element 0))
233          (new-hash-vector (when old-hash-vector
234                             (make-array new-size
235                                         :element-type '(unsigned-byte 32)
236                                         :initial-element #x80000000)))
237          (old-index-vector (hash-table-index-vector table))
238          (new-length (almost-primify
239                       (round (/ (float new-size)
240                                 (hash-table-rehash-threshold table)))))
241          (new-index-vector (make-array new-length
242                                        :element-type '(unsigned-byte 32)
243                                        :initial-element 0)))
244     (declare (type index new-size new-length old-size))
245
246     ;; Disable GC tricks on the OLD-KV-VECTOR.
247     (set-header-data old-kv-vector sb!vm:vector-normal-subtype)
248
249     ;; Copy over the kv-vector. The element positions should not move
250     ;; in case there are active scans.
251     (dotimes (i (* old-size 2))
252       (declare (type index i))
253       (setf (aref new-kv-vector i) (aref old-kv-vector i)))
254
255     ;; Copy over the hash-vector.
256     (when old-hash-vector
257       (dotimes (i old-size)
258         (setf (aref new-hash-vector i) (aref old-hash-vector i))))
259
260     (setf (hash-table-next-free-kv table) 0)
261     (setf (hash-table-needing-rehash table) 0)
262     ;; Rehash all the entries; last to first so that after the pushes
263     ;; the chains are first to last.
264     (do ((i (1- new-size) (1- i)))
265         ((zerop i))
266       (let ((key (aref new-kv-vector (* 2 i)))
267             (value (aref new-kv-vector (1+ (* 2 i)))))
268         (cond ((and (eq key +empty-ht-slot+)
269                     (eq value +empty-ht-slot+))
270                ;; Slot is empty, push it onto the free list.
271                (setf (aref new-next-vector i)
272                      (hash-table-next-free-kv table))
273                (setf (hash-table-next-free-kv table) i))
274               ((and new-hash-vector
275                     (not (= (aref new-hash-vector i) #x80000000)))
276                ;; Can use the existing hash value (not EQ based)
277                (let* ((hashing (aref new-hash-vector i))
278                       (index (rem hashing new-length))
279                       (next (aref new-index-vector index)))
280                  (declare (type index index)
281                           (type hash hashing))
282                  ;; Push this slot into the next chain.
283                  (setf (aref new-next-vector i) next)
284                  (setf (aref new-index-vector index) i)))
285               (t
286                ;; EQ base hash.
287                ;; Enable GC tricks.
288                (set-header-data new-kv-vector
289                                 sb!vm:vector-valid-hashing-subtype)
290                (let* ((hashing (pointer-hash key))
291                       (index (rem hashing new-length))
292                       (next (aref new-index-vector index)))
293                  (declare (type index index)
294                           (type hash hashing))
295                  ;; Push this slot onto the next chain.
296                  (setf (aref new-next-vector i) next)
297                  (setf (aref new-index-vector index) i))))))
298     (setf (hash-table-table table) new-kv-vector)
299     (setf (hash-table-index-vector table) new-index-vector)
300     (setf (hash-table-next-vector table) new-next-vector)
301     (setf (hash-table-hash-vector table) new-hash-vector)
302     ;; Shrink the old vectors to 0 size to help the conservative GC.
303     (shrink-vector old-kv-vector 0)
304     (shrink-vector old-index-vector 0)
305     (shrink-vector old-next-vector 0)
306     (when old-hash-vector
307       (shrink-vector old-hash-vector 0))
308     (setf (hash-table-rehash-trigger table) new-size))
309   (values))
310
311 ;;; Use the same size as before, re-using the vectors.
312 (defun rehash-without-growing (table)
313   (declare (type hash-table table))
314   (let* ((kv-vector (hash-table-table table))
315          (next-vector (hash-table-next-vector table))
316          (hash-vector (hash-table-hash-vector table))
317          (size (length next-vector))
318          (index-vector (hash-table-index-vector table))
319          (length (length index-vector)))
320     (declare (type index size length)
321              (type (simple-array (unsigned-byte 32) (*))))
322
323     ;; Disable GC tricks, they will be re-enabled during the re-hash
324     ;; if necesary.
325     (set-header-data kv-vector sb!vm:vector-normal-subtype)
326
327     ;; Rehash all the entries.
328     (setf (hash-table-next-free-kv table) 0)
329     (setf (hash-table-needing-rehash table) 0)
330     (dotimes (i size)
331       (setf (aref next-vector i) 0))
332     (dotimes (i length)
333       (setf (aref index-vector i) 0))
334     (do ((i (1- size) (1- i)))
335         ((zerop i))
336       (let ((key (aref kv-vector (* 2 i)))
337             (value (aref kv-vector (1+ (* 2 i)))))
338         (cond ((and (eq key +empty-ht-slot+)
339                     (eq value +empty-ht-slot+))
340                ;; Slot is empty, push it onto free list.
341                (setf (aref next-vector i) (hash-table-next-free-kv table))
342                (setf (hash-table-next-free-kv table) i))
343               ((and hash-vector (not (= (aref hash-vector i) #x80000000)))
344                ;; Can use the existing hash value (not EQ based)
345                (let* ((hashing (aref hash-vector i))
346                       (index (rem hashing length))
347                       (next (aref index-vector index)))
348                  (declare (type index index))
349                  ;; Push this slot into the next chain.
350                  (setf (aref next-vector i) next)
351                  (setf (aref index-vector index) i)))
352               (t
353                ;; EQ base hash.
354                ;; Enable GC tricks.
355                (set-header-data kv-vector sb!vm:vector-valid-hashing-subtype)
356                (let* ((hashing (pointer-hash key))
357                       (index (rem hashing length))
358                       (next (aref index-vector index)))
359                  (declare (type index index)
360                           (type hash hashing))
361                  ;; Push this slot into the next chain.
362                  (setf (aref next-vector i) next)
363                  (setf (aref index-vector index) i)))))))
364   (values))
365
366 (defun flush-needing-rehash (table)
367   (let* ((kv-vector (hash-table-table table))
368          (index-vector (hash-table-index-vector table))
369          (next-vector (hash-table-next-vector table))
370          (length (length index-vector)))
371     (do ((next (hash-table-needing-rehash table)))
372         ((zerop next))
373       (declare (type index next))
374       (let* ((key (aref kv-vector (* 2 next)))
375              (hashing (pointer-hash key))
376              (index (rem hashing length))
377              (temp (aref next-vector next)))
378         (setf (aref next-vector next) (aref index-vector index))
379         (setf (aref index-vector index) next)
380         (setf next temp))))
381   (setf (hash-table-needing-rehash table) 0)
382   (values))
383
384 (defun gethash (key hash-table &optional default)
385   #!+sb-doc
386   "Finds the entry in HASH-TABLE whose key is KEY and returns the associated
387    value and T as multiple values, or returns DEFAULT and NIL if there is no
388    such entry. Entries can be added using SETF."
389   (declare (type hash-table hash-table)
390            (values t (member t nil)))
391   (without-gcing
392    (cond ((= (get-header-data (hash-table-table hash-table))
393              sb!vm:vector-must-rehash-subtype)
394           (rehash-without-growing hash-table))
395          ((not (zerop (hash-table-needing-rehash hash-table)))
396           (flush-needing-rehash hash-table)))
397    ;; Search for key in the hash table.
398    (multiple-value-bind (hashing eq-based)
399        (funcall (hash-table-hash-fun hash-table) key)
400      (declare (type hash hashing))
401      (let* ((index-vector (hash-table-index-vector hash-table))
402             (length (length index-vector))
403             (index (rem hashing length))
404             (next (aref index-vector index))
405             (table (hash-table-table hash-table))
406             (next-vector (hash-table-next-vector hash-table))
407             (hash-vector (hash-table-hash-vector hash-table))
408             (test-fun (hash-table-test-fun hash-table)))
409        (declare (type index index))
410        ;; Search next-vector chain for a matching key.
411        (if (or eq-based (not hash-vector))
412            (do ((next next (aref next-vector next)))
413                ((zerop next) (values default nil))
414              (declare (type index next))
415              (when (eq key (aref table (* 2 next)))
416                (return (values (aref table (1+ (* 2 next))) t))))
417            (do ((next next (aref next-vector next)))
418                ((zerop next) (values default nil))
419              (declare (type index next))
420              (when (and (= hashing (aref hash-vector next))
421                         (funcall test-fun key (aref table (* 2 next))))
422                ;; Found.
423                (return (values (aref table (1+ (* 2 next))) t)))))))))
424
425 ;;; so people can call #'(SETF GETHASH)
426 (defun (setf gethash) (new-value key table &optional default)
427   (declare (ignore default))
428   (%puthash key table new-value))
429
430 (defun %puthash (key hash-table value)
431   (declare (type hash-table hash-table))
432   (aver (hash-table-index-vector hash-table))
433   (without-gcing
434    ;; We need to rehash here so that a current key can be found if it
435    ;; exists. Check that there is room for one more entry. May not be
436    ;; needed if the key is already present.
437    (cond ((zerop (hash-table-next-free-kv hash-table))
438           (rehash hash-table))
439          ((= (get-header-data (hash-table-table hash-table))
440              sb!vm:vector-must-rehash-subtype)
441           (rehash-without-growing hash-table))
442          ((not (zerop (hash-table-needing-rehash hash-table)))
443           (flush-needing-rehash hash-table)))
444
445    ;; Search for key in the hash table.
446    (multiple-value-bind (hashing eq-based)
447        (funcall (hash-table-hash-fun hash-table) key)
448      (declare (type hash hashing))
449      (let* ((index-vector (hash-table-index-vector hash-table))
450             (length (length index-vector))
451             (index (rem hashing length))
452             (next (aref index-vector index))
453             (kv-vector (hash-table-table hash-table))
454             (next-vector (hash-table-next-vector hash-table))
455             (hash-vector (hash-table-hash-vector hash-table))
456             (test-fun (hash-table-test-fun hash-table)))
457        (declare (type index index))
458
459        (cond ((or eq-based (not hash-vector))
460               (when eq-based
461                 (set-header-data kv-vector sb!vm:vector-valid-hashing-subtype))
462
463               ;; Search next-vector chain for a matching key.
464               (do ((next next (aref next-vector next)))
465                   ((zerop next))
466                 (declare (type index next))
467                 (when (eq key (aref kv-vector (* 2 next)))
468                   ;; Found, just replace the value.
469                   (setf (aref kv-vector (1+ (* 2 next))) value)
470                   (return-from %puthash value))))
471              (t
472               ;; Search next-vector chain for a matching key.
473               (do ((next next (aref next-vector next)))
474                   ((zerop next))
475                 (declare (type index next))
476                 (when (and (= hashing (aref hash-vector next))
477                            (funcall test-fun key
478                                     (aref kv-vector (* 2 next))))
479                   ;; Found, just replace the value.
480                   (setf (aref kv-vector (1+ (* 2 next))) value)
481                   (return-from %puthash value)))))
482
483        ;; Pop a KV slot off the free list
484        (let ((free-kv-slot (hash-table-next-free-kv hash-table)))
485          ;; Double-check for overflow.
486          (aver (not (zerop free-kv-slot)))
487          (setf (hash-table-next-free-kv hash-table)
488                (aref next-vector free-kv-slot))
489          (incf (hash-table-number-entries hash-table))
490
491          (setf (aref kv-vector (* 2 free-kv-slot)) key)
492          (setf (aref kv-vector (1+ (* 2 free-kv-slot))) value)
493
494          ;; Setup the hash-vector if necessary.
495          (when hash-vector
496            (if (not eq-based)
497                (setf (aref hash-vector free-kv-slot) hashing)
498                (aver (= (aref hash-vector free-kv-slot) #x80000000))))
499
500          ;; Push this slot into the next chain.
501          (setf (aref next-vector free-kv-slot) next)
502          (setf (aref index-vector index) free-kv-slot)))))
503   value)
504
505 (defun remhash (key hash-table)
506   #!+sb-doc
507   "Remove the entry in HASH-TABLE associated with KEY. Returns T if there
508    was such an entry, and NIL if not."
509   (declare (type hash-table hash-table)
510            (values (member t nil)))
511   (without-gcing
512    ;; We need to rehash here so that a current key can be found if it
513    ;; exists.
514    (cond ((= (get-header-data (hash-table-table hash-table))
515              sb!vm:vector-must-rehash-subtype)
516           (rehash-without-growing hash-table))
517          ((not (zerop (hash-table-needing-rehash hash-table)))
518           (flush-needing-rehash hash-table)))
519
520    ;; Search for key in the hash table.
521    (multiple-value-bind (hashing eq-based)
522        (funcall (hash-table-hash-fun hash-table) key)
523      (declare (type hash hashing))
524      (let* ((index-vector (hash-table-index-vector hash-table))
525             (length (length index-vector))
526             (index (rem hashing length))
527             (next (aref index-vector index))
528             (table (hash-table-table hash-table))
529             (next-vector (hash-table-next-vector hash-table))
530             (hash-vector (hash-table-hash-vector hash-table))
531             (test-fun (hash-table-test-fun hash-table)))
532        (declare (type index index next))
533        (cond ((zerop next)
534               nil)
535              ((if (or eq-based (not hash-vector))
536                   (eq key (aref table (* 2 next)))
537                   (and (= hashing (aref hash-vector next))
538                        (funcall test-fun key (aref table (* 2 next)))))
539
540               ;; FIXME: Substantially the same block of code seems to
541               ;; appear in all three cases. (In the first case, it
542               ;; appear bare; in the other two cases, it's wrapped in
543               ;; DO.) It should be defined in a separate (possibly
544               ;; inline) DEFUN or FLET.
545               
546               ;; Mark slot as empty.
547               (setf (aref table (* 2 next)) +empty-ht-slot+
548                     (aref table (1+ (* 2 next))) +empty-ht-slot+)
549               ;; Update the index-vector pointer.
550               (setf (aref index-vector index) (aref next-vector next))
551               ;; Push KV slot onto free chain.
552               (setf (aref next-vector next)
553                     (hash-table-next-free-kv hash-table))
554               (setf (hash-table-next-free-kv hash-table) next)
555               (when hash-vector
556                 (setf (aref hash-vector next) #x80000000))
557               (decf (hash-table-number-entries hash-table))
558               t)
559              ;; Search next-vector chain for a matching key.
560              ((or eq-based (not hash-vector))
561               ;; EQ based
562               (do ((prior next next)
563                    (next (aref next-vector next) (aref next-vector next)))
564                   ((zerop next) nil)
565                 (declare (type index next))
566                 (when (eq key (aref table (* 2 next)))
567                   ;; Mark slot as empty.
568                   (setf (aref table (* 2 next)) +empty-ht-slot+
569                         (aref table (1+ (* 2 next))) +empty-ht-slot+)
570                   ;; Update the prior pointer in the chain to skip this.
571                   (setf (aref next-vector prior) (aref next-vector next))
572                   ;; Push KV slot onto free chain.
573                   (setf (aref next-vector next)
574                         (hash-table-next-free-kv hash-table))
575                   (setf (hash-table-next-free-kv hash-table) next)
576                   (when hash-vector
577                     (setf (aref hash-vector next) #x80000000))
578                   (decf (hash-table-number-entries hash-table))
579                   (return t))))
580              (t
581               ;; not EQ based
582               (do ((prior next next)
583                    (next (aref next-vector next) (aref next-vector next)))
584                   ((zerop next) nil)
585                 (declare (type index next))
586                 (when (and (= hashing (aref hash-vector next))
587                            (funcall test-fun key (aref table (* 2 next))))
588                   ;; Mark slot as empty.
589                   (setf (aref table (* 2 next)) +empty-ht-slot+)
590                   (setf (aref table (1+ (* 2 next))) +empty-ht-slot+)
591                   ;; Update the prior pointer in the chain to skip this.
592                   (setf (aref next-vector prior) (aref next-vector next))
593                   ;; Push KV slot onto free chain.
594                   (setf (aref next-vector next)
595                         (hash-table-next-free-kv hash-table))
596                   (setf (hash-table-next-free-kv hash-table) next)
597                   (when hash-vector
598                     (setf (aref hash-vector next) #x80000000))
599                   (decf (hash-table-number-entries hash-table))
600                   (return t)))))))))
601
602 (defun clrhash (hash-table)
603   #!+sb-doc
604   "This removes all the entries from HASH-TABLE and returns the hash table
605    itself."
606   (let* ((kv-vector (hash-table-table hash-table))
607          (kv-length (length kv-vector))
608          (next-vector (hash-table-next-vector hash-table))
609          (hash-vector (hash-table-hash-vector hash-table))
610          (size (length next-vector))
611          (index-vector (hash-table-index-vector hash-table))
612          (length (length index-vector)))
613     ;; Disable GC tricks.
614     (set-header-data kv-vector sb!vm:vector-normal-subtype)
615     ;; Mark all slots as empty by setting all keys and values to magic
616     ;; tag.
617     (do ((i 2 (1+ i)))
618         ((>= i kv-length))
619       (setf (aref kv-vector i) +empty-ht-slot+))
620     (aver (eq (aref kv-vector 0) hash-table))
621     ;; Set up the free list, all free.
622     (do ((i 1 (1+ i)))
623         ((>= i (1- size)))
624       (setf (aref next-vector i) (1+ i)))
625     (setf (aref next-vector (1- size)) 0)
626     (setf (hash-table-next-free-kv hash-table) 1)
627     (setf (hash-table-needing-rehash hash-table) 0)
628     ;; Clear the index-vector.
629     (dotimes (i length)
630       (setf (aref index-vector i) 0))
631     ;; Clear the hash-vector.
632     (when hash-vector
633       (dotimes (i size)
634         (setf (aref hash-vector i) #x80000000))))
635   (setf (hash-table-number-entries hash-table) 0)
636   hash-table)
637 \f
638 ;;;; MAPHASH
639
640 ;;; FIXME: This should be made into a compiler transform for two reasons:
641 ;;;   1. It would then be available for compiling the entire system,
642 ;;;      not only parts of the system which are defined after DEFUN MAPHASH.
643 ;;;   2. It could be conditional on compilation policy, so that
644 ;;;      it could be compiled as a full call instead of an inline
645 ;;;      expansion when SPACE>SPEED. (Not only would this save space,
646 ;;;      it might actually be faster when a call is made from byte-compiled
647 ;;;      code.)
648 (declaim (inline maphash))
649 (defun maphash (function-designator hash-table)
650   #!+sb-doc
651   "For each entry in HASH-TABLE, call the designated two-argument function
652    on the key and value of the entry. Return NIL."
653   (let ((fun (%coerce-callable-to-function function-designator))
654         (size (length (hash-table-next-vector hash-table))))
655     (declare (type function fun))
656     (do ((i 1 (1+ i)))
657         ((>= i size))
658       (declare (type index i))
659       (let* ((kv-vector (hash-table-table hash-table))
660              (key (aref kv-vector (* 2 i)))
661              (value (aref kv-vector (1+ (* 2 i)))))
662         (unless (and (eq key +empty-ht-slot+)
663                      (eq value +empty-ht-slot+))
664           (funcall fun key value))))))
665 \f
666 ;;;; methods on HASH-TABLE
667
668 ;;; Return a list of keyword args and values to use for MAKE-HASH-TABLE
669 ;;; when reconstructing HASH-TABLE.
670 (defun %hash-table-ctor-args (hash-table)
671   (when (hash-table-weak-p hash-table)
672     ;; FIXME: This might actually work with no trouble, but as of
673     ;; sbcl-0.6.12.10 when this code was written, weak hash tables
674     ;; weren't working yet, so I couldn't test it. When weak hash
675     ;; tables are supported again, this should be fixed.
676     (error "can't dump weak hash tables readably")) ; defensive programming..
677   `(:test             ',(hash-table-test             hash-table)
678     :size             ',(hash-table-size             hash-table)
679     :rehash-size      ',(hash-table-rehash-size      hash-table)
680     :rehash-threshold ',(hash-table-rehash-threshold hash-table)))
681
682 ;;; Return an association list representing the same data as HASH-TABLE.
683 (defun %hash-table-alist (hash-table)
684   (let ((result nil))
685     (maphash (lambda (key value)
686                (push (cons key value) result))
687              hash-table)
688     result))
689
690 ;;; Stuff an association list into HASH-TABLE. Return the hash table,
691 ;;; so that we can use this for the *PRINT-READABLY* case in
692 ;;; PRINT-OBJECT (HASH-TABLE T) without having to worry about LET
693 ;;; forms and readable gensyms and stuff.
694 (defun %stuff-hash-table (hash-table alist)
695   (dolist (x alist)
696     (setf (gethash (car x) hash-table) (cdr x)))
697   hash-table)
698
699 (def!method print-object ((hash-table hash-table) stream)
700   (declare (type stream stream))
701   (cond ((not *print-readably*)
702          (print-unreadable-object (hash-table stream :type t :identity t)
703            (format stream
704                    ":TEST ~S :COUNT ~S"
705                    (hash-table-test hash-table)
706                    (hash-table-count hash-table))))
707         ((not *read-eval*)
708          (error "can't print hash tables readably without *READ-EVAL*"))
709         (t
710          (with-standard-io-syntax
711           (format stream
712                   "#.~W"
713                   `(%stuff-hash-table (make-hash-table ,@(%hash-table-ctor-args
714                                                           hash-table))
715                                      ',(%hash-table-alist hash-table)))))))
716
717 (def!method make-load-form ((hash-table hash-table) &optional environment)
718   (declare (ignore environment))
719   (values `(make-hash-table ,@(%hash-table-ctor-args hash-table))
720           `(%stuff-hash-table ,hash-table ',(%hash-table-alist hash-table))))