Multiple hash tables supported.
authorGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Fri, 16 Aug 1991 15:40:17 +0000 (15:40 +0000)
committerGuillermo J. Rozas <edu/mit/csail/zurich/gjr>
Fri, 16 Aug 1991 15:40:17 +0000 (15:40 +0000)
v7/src/runtime/hash.scm

index 4db6dd5bd1baa5ba26fe294940fe06f79b1764e3..934b0813a7d9f8ac61d51eae0bbb7b860e5ad27f 100644 (file)
@@ -1,8 +1,8 @@
 #| -*-Scheme-*-
 
-$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/runtime/hash.scm,v 14.2 1989/09/20 15:04:15 cph Rel $
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/runtime/hash.scm,v 14.3 1991/08/16 15:40:17 jinx Exp $
 
-Copyright (c) 1988 Massachusetts Institute of Technology
+Copyright (c) 1988-91 Massachusetts Institute of Technology
 
 This material was developed by the Scheme project at the Massachusetts
 Institute of Technology, Department of Electrical Engineering and
@@ -32,17 +32,16 @@ Technology nor of any adaptation thereof in any advertising,
 promotional, or sales literature without prior written consent from
 MIT in each case. |#
 
-;;;; Object Hashing, populations, and 2D tables
+;;;; Object Hashing
 ;;; package: (runtime hash)
 
 (declare (usual-integrations))
 \f
 ;;;; Object hashing
 
-;;; The hashing code, and the population code below, depend on weak
-;;; conses supported by the microcode.  In particular, both pieces of
-;;; code depend on the fact that the car of a weak cons becomes #F if
-;;; the object is garbage collected.
+;;; The hashing code depends on weak conses supported by the
+;;; microcode.  In particular, it depends on the fact that the car of
+;;; a weak cons becomes #F if the object is garbage collected.
 
 ;;; Important: This code must be rewritten for a parallel processor,
 ;;; since two processors may be updating the data structures
@@ -86,91 +85,157 @@ MIT in each case. |#
 ;;; object-unhash's back.  Then object-unhash does not need to be
 ;;; locked against garbage collection.
 \f
+(define default/hash-table-size 313)
+(define default-hash-table)
+(define all-hash-tables)
+
 (define (initialize-package!)
-  (set! next-hash-number 1)
-  (set! hash-table-size default/hash-table-size)
-  (set! unhash-table (make-vector hash-table-size '()))
-  (set! hash-table (make-vector (1+ hash-table-size) '()))
-  ;; Could use `primitive-object-set!' to clobber the manifest type
-  ;; code instead of allocating another word here.
-  (vector-set! hash-table
-              0
-              ((ucode-primitive primitive-object-set-type)
-               (ucode-type manifest-special-nm-vector)
-               (make-non-pointer-object hash-table-size)))
-  (let loop ((n 0))
-    (if (< n hash-table-size)
-       (begin
-         (vector-set! unhash-table n (cons true '()))
-         (loop (1+ n)))))
+  (set! all-hash-tables (weak-cons 0 '()))
+  (set! default-hash-table (hash-table/make))
   (add-event-receiver! event:after-restore (lambda () (gc-flip)))
-  (add-gc-daemon! rehash-gc-daemon))
+  (add-gc-daemon! rehash-all-gc-daemon))
 
-(define default/hash-table-size 313)
-(define next-hash-number)
-(define hash-table-size)
-(define unhash-table)
-(define hash-table)
+(define-structure (hash-table
+                  (conc-name hash-table/)
+                  (constructor %hash-table/make))
+  (size)
+  (next-number)
+  (hash-table)
+  (unhash-table))
+
+(define (hash-table/make #!optional size)
+  (let* ((size (if (default-object? size)
+                  default/hash-table-size
+                  size))
+        (table
+         (%hash-table/make
+          size
+          1
+          (let ((table (make-vector (1+ size) '())))
+            (vector-set! table
+                         0
+                         ((ucode-primitive primitive-object-set-type)
+                          (ucode-type manifest-special-nm-vector)
+                          (make-non-pointer-object size)))
+            ((ucode-primitive primitive-object-set-type)
+             (ucode-type non-marked-vector)
+             table))
+          (let ((table (make-vector size '())))
+            (let loop ((n 0))
+              (if (fix:< n size)
+                  (begin
+                    (vector-set! table n (cons true '()))
+                    (loop (fix:+ n 1)))))
+            table))))
+    (weak-set-cdr! all-hash-tables
+                  (weak-cons table (weak-cdr all-hash-tables)))
+    table))
 
-(define (hash x)
+(define (hash x #!optional table)
   (if (eq? x false)
       0
-      (object-hash x)))
+      (object-hash x
+                  (if (default-object? table)
+                      default-hash-table
+                      table)
+                  true)))
 
-(define (unhash n)
+(define (unhash n #!optional table)
   (if (zero? n)
       false
-      (or (object-unhash n)
-         (error "unhash: Not a valid hash number" n))))
+      (let ((table (if (default-object? table)
+                      default-hash-table
+                      table)))
+       (or (object-unhash n table)
+           (error "unhash: Not a valid hash number" n table)))))
 
-(define (valid-hash-number? n)
+(define (valid-hash-number? n #!optional table)
   (or (zero? n)
-      (object-unhash n)))
+      (object-unhash n (if (default-object? table)
+                          default-hash-table
+                          table))))
+
+(define (object-hashed? n #!optional table)
+  (or (eq? x false)
+      (object-hash x
+                  (if (default-object? table)
+                      default-hash-table
+                      table)
+                  false)))  
 \f
 ;;; This is not dangerous because assq is a primitive and does not
-;;; cause consing.  The rest of the consing (including that by the
-;;; interpreter) is a small bounded amount.
-
-(define (object-hash object)
-  (with-absolutely-no-interrupts
-   (lambda ()
-     (let* ((hash-index (1+ (modulo (object-datum object) hash-table-size)))
-           (bucket (vector-ref hash-table hash-index))
-           (association (assq object bucket)))
-       (if association
-          (cdr association)
-          (let ((pair (cons object next-hash-number))
-                (result next-hash-number)
-                (unhash-bucket
-                 (vector-ref unhash-table
-                             (modulo next-hash-number hash-table-size))))
-            (set! next-hash-number (1+ next-hash-number))
-            (vector-set! hash-table hash-index (cons pair bucket))
-            (set-cdr! unhash-bucket
-                      (cons (object-new-type (ucode-type weak-cons) pair)
-                            (cdr unhash-bucket)))
-            result))))))
+;;; cons.  The rest of the consing (including that by the interpreter)
+;;; is a small bounded amount.
+;;;
+;;; NOTE: assq is no longer a primitive.  This works fine if assq is
+;;; compiled, but can lose if it is interpreted.
+
+(define (object-hash object #!optional table insert?)
+  (let ((table (cond ((default-object? table)
+                     default-hash-table)
+                    ((hash-table? table)
+                     table)
+                    (else
+                     (error "object-hash: Not a hash table" table))))
+       (insert? (or (default-object? insert?)
+                    insert?)))
+    (with-absolutely-no-interrupts
+      (lambda ()
+       (let* ((hash-index (fix:+ 1
+                                 (modulo (object-datum object)
+                                         (hash-table/size table))))
+              (the-hash-table
+               ((ucode-primitive primitive-object-set-type)
+                (ucode-type vector)
+                (hash-table/hash-table table)))
+              (bucket (vector-ref the-hash-table hash-index))
+              (association (assq object bucket)))
+         (cond (association
+                (cdr association))
+               ((not insert?)
+                false)
+               (else
+                (let ((result (hash-table/next-number table)))
+                  (let ((pair (cons object result))
+                        (unhash-bucket
+                         (vector-ref (hash-table/unhash-table table)
+                                     (modulo result
+                                             (hash-table/size table)))))
+                    (set-hash-table/next-number! table (1+ result))
+                    (vector-set! the-hash-table
+                                 hash-index
+                                 (cons pair bucket))
+                    (set-cdr! unhash-bucket
+                              (cons (object-new-type (ucode-type weak-cons) pair)
+                                    (cdr unhash-bucket)))
+                    result)))))))))
 
 ;;; This is safe because it locks the garbage collector out only for a
 ;;; little time, enough to tag the bucket being searched, so that the
 ;;; daemon will not splice that bucket.
 
-(define (object-unhash number)
-  (let ((index (modulo number hash-table-size)))
+(define (object-unhash number #!optional table)
+  (let* ((table (cond ((default-object? table)
+                      default-hash-table)
+                     ((hash-table? table)
+                      table)
+                     (else
+                      (error "object-hash: Not a hash table" table))))
+        (index (modulo number (hash-table/size table))))
     (with-absolutely-no-interrupts
-     (lambda ()
-       (let ((bucket (vector-ref unhash-table index)))
-        (set-car! bucket false)
-        (let ((result
-               (without-interrupts
-                (lambda ()
-                  (let loop ((l (cdr bucket)))
-                    (cond ((null? l) false)
-                          ((= number (system-pair-cdr (car l)))
-                           (system-pair-car (car l)))
-                          (else (loop (cdr l)))))))))
-          (set-car! bucket true)
-          result))))))
+      (lambda ()
+       (let ((bucket (vector-ref (hash-table/unhash-table table) index)))
+         (set-car! bucket false)
+         (let ((result
+                (without-interrupts
+                  (lambda ()
+                    (let loop ((l (cdr bucket)))
+                      (cond ((null? l) false)
+                            ((= number (system-pair-cdr (car l)))
+                             (system-pair-car (car l)))
+                            (else (loop (cdr l)))))))))
+           (set-car! bucket true)
+           result))))))
 \f
 ;;;; Rehash daemon
 
@@ -184,50 +249,67 @@ MIT in each case. |#
 ;;; is SNM rather than NM to make the buckets be relocated at band
 ;;; load/restore time.
 
-;;; **** There is also a problem with intermediate bignums being
-;;; consed by `rehash' while computing `index'.  This must be fixed
-;;; before the Scheme code below can be used. ****
-
 ;;; Until this code is compiled, and therefore safe, it is replaced by
 ;;; a primitive.  See the installation code below.
 #|
-(define (rehash-gc-daemon)
-  (let cleanup ((n hash-table-size))
-    (if (not (zero? n))
-       (begin
-         (vector-set! hash-table n '())
-         (cleanup (-1+ n)))))
-  (let outer ((n (-1+ hash-table-size)))
-    (if (not (negative? n))
-       (let ((bucket (vector-ref unhash-table n)))
-         (if (car bucket)
-             (let inner1 ((l1 bucket) (l2 (cdr bucket)))
-               (cond ((null? l2)
-                      (outer (-1+ n)))
-                     ((eq? (system-pair-car (car l2)) false)
-                      (set-cdr! l1 (cdr l2))
-                      (inner1 l1 (cdr l1)))
-                     (else
-                      (rehash (car l2))
-                      (inner1 l2 (cdr l2)))))
-             (let inner2 ((l (cdr bucket)))
-               (cond ((null? l)
-                      (outer (-1+ n)))
-                     ((eq? (system-pair-car (car l)) false)
-                      (inner2 (cdr l)))
-                     (else
-                      (rehash (car l))
-                      (inner2 (cdr l))))))))))
-
-(define (rehash weak-pair)
-  (let ((index
-        (1+ (modulo (object-datum (system-pair-car weak-pair))
-                    hash-table-size))))
-    (vector-set! hash-table
-                index
-                (cons (object-new-type (ucode-type pair) weak-pair)
-                      (vector-ref hash-table index)))
-    unspecific))
+(define (hash-table/rehash table)
+  (let ((hash-table-size (hash-table/size table))
+       (hash-table ((ucode-primitive primitive-object-set-type)
+                    (ucode-type vector)
+                    (hash-table/hash-table table)))
+       (unhash-table (hash-table/unhash-table table)))
+
+    (define (rehash weak-pair)
+      (let ((index
+            (fix:+ 1 (modulo (object-datum (system-pair-car weak-pair))
+                             hash-table-size))))
+       (vector-set! hash-table
+                    index
+                    (cons (object-new-type (ucode-type pair) weak-pair)
+                          (vector-ref hash-table index)))
+       unspecific))
+
+    (let cleanup ((n hash-table-size))
+      (if (not (fix:= n 0))
+         (begin
+           (vector-set! hash-table n '())
+           (cleanup (fix:- n 1)))))
+
+    (let outer ((n (fix:- hash-table-size 1)))
+      (if (not (fix:< n 0))
+         (let ((bucket (vector-ref unhash-table n)))
+           (if (car bucket)
+               (let inner1 ((l1 bucket) (l2 (cdr bucket)))
+                 (cond ((null? l2)
+                        (outer (fix:- n 1)))
+                       ((eq? (system-pair-car (car l2)) false)
+                        (set-cdr! l1 (cdr l2))
+                        (inner1 l1 (cdr l1)))
+                       (else
+                        (rehash (car l2))
+                        (inner1 l2 (cdr l2)))))
+               (let inner2 ((l (cdr bucket)))
+                 (cond ((null? l)
+                        (outer (fix:- n 1)))
+                       ((eq? (system-pair-car (car l)) false)
+                        (inner2 (cdr l)))
+                       (else
+                        (rehash (car l))
+                        (inner2 (cdr l)))))))))))
 |#
-(define (rehash-gc-daemon)
-  ((ucode-primitive rehash) unhash-table hash-table))
\ No newline at end of file
+
+(define-integrable (hash-table/rehash table)
+  ((ucode-primitive rehash) (hash-table/unhash-table table)
+                           (hash-table/hash-table table)))
+
+(define (rehash-all-gc-daemon)
+  (let loop ((l all-hash-tables)
+            (n (weak-cdr all-hash-tables)))
+    (cond ((null? n)
+          (weak-set-cdr! l n))
+         ((not (weak-pair/car? n))
+          (loop l (weak-cdr n)))
+         (else
+          (weak-set-cdr! l n)
+          (hash-table/rehash (weak-car n))
+          (loop n (weak-cdr n))))))
\ No newline at end of file