1.0.12.13: sequence optimizations: SUBSEQ, part 3
[sbcl.git] / src / code / array.lisp
index 3a9d703..4268f55 100644 (file)
@@ -323,71 +323,80 @@ of specialized arrays is supported."
 ;;; the type information is available. Finally, for each of these
 ;;; routines also provide a slow path, taken for arrays that are not
 ;;; vectors or not simple.
-(macrolet ((%define (table-name extra-params)
-             `(funcall
-               (the function
-                 (let ((tag 0)
-                       (offset
-                        #.(ecase sb!c:*backend-byte-order*
-                            (:little-endian
-                             (- sb!vm:other-pointer-lowtag))
-                            (:big-endian
-                             (- (1- sb!vm:n-word-bytes) sb!vm:other-pointer-lowtag)))))
-                   ;; WIDETAG-OF needs extra code to handle
-                   ;; LIST and FUNCTION lowtags. We're only
-                   ;; dispatching on other pointers, so let's
-                   ;; do the lowtag extraction manually.
-                   (when (sb!vm::%other-pointer-p array)
-                     (setf tag
-                           (sb!sys:sap-ref-8 (int-sap (get-lisp-obj-address array))
-                                             offset)))
-                   ;; SYMBOL-GLOBAL-VALUE is a performance hack
-                   ;; for threaded builds.
-                   (svref (sb!vm::symbol-global-value ',table-name) tag)))
-               array index ,@extra-params))
-           (define (accessor-name slow-accessor-name table-name extra-params
-                                  check-bounds)
-               `(progn
-                 (defvar ,table-name)
-                 (defun ,accessor-name (array index ,@extra-params)
-                   (declare (optimize speed
-                                      ;; (SAFETY 0) is ok. All calls to
-                                      ;; these functions are generated by
-                                      ;; the compiler, so argument count
-                                      ;; checking isn't needed. Type checking
-                                      ;; is done implicitly via the widetag
-                                      ;; dispatch.
-                                      (safety 0)))
-                   (%define ,table-name ,extra-params))
-                 (defun ,slow-accessor-name (array index ,@extra-params)
-                   (declare (optimize speed (safety 0)))
-                   (if (not (%array-displaced-p array))
-                       ;; The reasonably quick path of non-displaced complex
-                       ;; arrays.
-                       (let ((array (%array-data-vector array)))
-                         (%define ,table-name ,extra-params))
-                       ;; The real slow path.
-                       (with-array-data
-                           ((vector array)
-                            (index (locally
-                                       (declare (optimize (speed 1) (safety 1)))
-                                     (,@check-bounds index)))
-                            (end)
-                            :force-inline t)
-                         (declare (ignore end))
-                         (,accessor-name vector index ,@extra-params)))))))
+(macrolet ((def (name table-name)
+             `(progn
+                (defvar ,table-name)
+                (defmacro ,name (array-var)
+                 `(the function
+                    (let ((tag 0)
+                          (offset
+                           #.(ecase sb!c:*backend-byte-order*
+                               (:little-endian
+                                (- sb!vm:other-pointer-lowtag))
+                               (:big-endian
+                                (- (1- sb!vm:n-word-bytes) sb!vm:other-pointer-lowtag)))))
+                      ;; WIDETAG-OF needs extra code to handle LIST and
+                      ;; FUNCTION lowtags. We're only dispatching on
+                      ;; other pointers, so let's do the lowtag
+                      ;; extraction manually.
+                      (when (sb!vm::%other-pointer-p ,array-var)
+                        (setf tag
+                              (sb!sys:sap-ref-8 (int-sap (get-lisp-obj-address ,array-var))
+                                                offset)))
+                      ;; SYMBOL-GLOBAL-VALUE is a performance hack
+                      ;; for threaded builds.
+                      (svref (sb!vm::symbol-global-value ',',table-name) tag)))))))
+  (def !find-data-vector-setter *data-vector-setters*)
+  (def !find-data-vector-setter/check-bounds *data-vector-setters/check-bounds*)
+  (def !find-data-vector-reffer *data-vector-reffers*)
+  (def !find-data-vector-reffer/check-bounds *data-vector-reffers/check-bounds*))
+
+(macrolet ((%ref (accessor-getter extra-params)
+             `(funcall (,accessor-getter array) array index ,@extra-params))
+           (define (accessor-name slow-accessor-name accessor-getter
+                                  extra-params check-bounds)
+             `(progn
+                (defun ,accessor-name (array index ,@extra-params)
+                  (declare (optimize speed
+                                     ;; (SAFETY 0) is ok. All calls to
+                                     ;; these functions are generated by
+                                     ;; the compiler, so argument count
+                                     ;; checking isn't needed. Type checking
+                                     ;; is done implicitly via the widetag
+                                     ;; dispatch.
+                                     (safety 0)))
+                  (%ref ,accessor-getter ,extra-params))
+                (defun ,slow-accessor-name (array index ,@extra-params)
+                  (declare (optimize speed (safety 0)))
+                  (if (not (%array-displaced-p array))
+                      ;; The reasonably quick path of non-displaced complex
+                      ;; arrays.
+                      (let ((array (%array-data-vector array)))
+                        (%ref ,accessor-getter ,extra-params))
+                      ;; The real slow path.
+                      (with-array-data
+                          ((vector array)
+                           (index (locally
+                                      (declare (optimize (speed 1) (safety 1)))
+                                    (,@check-bounds index)))
+                           (end)
+                           :force-inline t)
+                        (declare (ignore end))
+                        (,accessor-name vector index ,@extra-params)))))))
   (define hairy-data-vector-ref slow-hairy-data-vector-ref
-    *data-vector-reffers* nil (progn))
+    !find-data-vector-reffer
+    nil (progn))
   (define hairy-data-vector-set slow-hairy-data-vector-set
-    *data-vector-setters* (new-value) (progn))
+    !find-data-vector-setter
+    (new-value) (progn))
   (define hairy-data-vector-ref/check-bounds
       slow-hairy-data-vector-ref/check-bounds
-    *data-vector-reffers/check-bounds* nil
-    (%check-bound array (array-dimension array 0)))
+    !find-data-vector-reffer/check-bounds
+    nil (%check-bound array (array-dimension array 0)))
   (define hairy-data-vector-set/check-bounds
       slow-hairy-data-vector-set/check-bounds
-    *data-vector-setters/check-bounds* (new-value)
-    (%check-bound array (array-dimension array 0))))
+    !find-data-vector-setter/check-bounds
+    (new-value) (%check-bound array (array-dimension array 0))))
 
 (defun hairy-ref-error (array index &optional new-value)
   (declare (ignore index new-value))