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