0.8.1.36:
[sbcl.git] / src / code / sxhash.lisp
index 61f4d29..facc633 100644 (file)
 (deftransform sxhash ((x) (simple-bit-vector))
   `(let ((result 410823708))
     (declare (type fixnum result))
-    (mixf result (sxhash (length x)))
-    (do* ((i sb!vm:vector-data-offset (+ i 1))
-         ;; FIXME: should we respect DEPTHOID?  SXHASH on strings
-         ;; doesn't seem to...
-         (end (+ sb!vm:vector-data-offset
-                 (ceiling (length x) sb!vm:n-word-bits))))
-        ((= i end) result)
-      (declare (type index i end))
-      (let ((num
-            (if (= i (1- end))
-                (logand
-                 (ash (1- (ash 1 (mod (length x) sb!vm:n-word-bits)))
-                      ,(ecase sb!c:*backend-byte-order*
-                         (:little-endian 0)
-                         (:big-endian
-                          '(- sb!vm:n-word-bits
-                              (mod (length x) sb!vm:n-word-bits)))))
-                 (%raw-bits x i))
-                (%raw-bits x i))))
-       (declare (type (unsigned-byte 32) num))
-       (mixf result ,(ecase sb!c:*backend-byte-order*
-                       (:little-endian '(logand num most-positive-fixnum))
-                       ;; FIXME: I'm not certain that N-LOWTAG-BITS
-                       ;; is the clearest way of expressing this:
-                       ;; it's essentially the difference between
-                       ;; `(UNSIGNED-BYTE ,SB!VM:N-WORD-BITS) and
-                       ;; (AND FIXNUM UNSIGNED-BYTE).
-                       (:big-endian '(ash num (- sb!vm:n-lowtag-bits)))))))))
+    (let ((length (length x)))
+      (cond
+       ((= length 0) (mix result (sxhash 0)))
+       (t
+        (mixf result (sxhash (length x)))
+        (do* ((i sb!vm:vector-data-offset (+ i 1))
+              ;; FIXME: should we respect DEPTHOID?  SXHASH on
+              ;; strings doesn't seem to...
+              (end-1 (+ sb!vm:vector-data-offset
+                        (floor (1- length) sb!vm:n-word-bits))))
+             ((= i end-1)
+              (let ((num
+                     (logand
+                      (ash (1- (ash 1 (mod length sb!vm:n-word-bits)))
+                           ,(ecase sb!c:*backend-byte-order*
+                              (:little-endian 0)
+                              (:big-endian
+                               '(- sb!vm:n-word-bits
+                                   (mod length sb!vm:n-word-bits)))))
+                      (%raw-bits x i))))
+                (declare (type (unsigned-byte 32) num))
+                (mix result ,(ecase sb!c:*backend-byte-order*
+                               (:little-endian
+                                '(logand num most-positive-fixnum))
+                               (:big-endian
+                                '(ash num (- sb!vm:n-lowtag-bits)))))))
+          (declare (type index i end-1))
+          (let ((num (%raw-bits x i)))
+            (declare (type (unsigned-byte 32) num))
+            (mixf result ,(ecase sb!c:*backend-byte-order*
+                            (:little-endian
+                             '(logand num most-positive-fixnum))
+                            ;; FIXME: I'm not certain that
+                            ;; N-LOWTAG-BITS is the clearest way of
+                            ;; expressing this: it's essentially the
+                            ;; difference between `(UNSIGNED-BYTE
+                            ;; ,SB!VM:N-WORD-BITS) and (AND FIXNUM
+                            ;; UNSIGNED-BYTE).
+                            (:big-endian
+                             '(ash num (- sb!vm:n-lowtag-bits))))))))))))
 
 ;;; Some other common SXHASH cases are defined as DEFTRANSFORMs in
 ;;; order to avoid having to do TYPECASE at runtime.