:node node
:policy (> speed space))
"inline non-SIMPLE-vector-handling logic"
- (let ((element-type (upgraded-element-type-specifier-or-give-up array)))
- `(%with-array-data-macro array start end
- :unsafe? ,(policy node (= safety 0))
- :element-type ,element-type)))
+ (let ((element-type (upgraded-element-type-specifier-or-give-up array))
+ (type (lvar-type array)))
+ (if (and (array-type-p type)
+ (listp (array-type-dimensions type))
+ (not (null (cdr (array-type-dimensions type)))))
+ ;; If it's a simple multidimensional array, then just return its
+ ;; data vector directly rather than going through
+ ;; %WITH-ARRAY-DATA-MACRO. SBCL doesn't generally generate code
+ ;; that would use this currently, but we have encouraged users
+ ;; to use WITH-ARRAY-DATA and we may use it ourselves at some
+ ;; point in the future for optimized libraries or similar.
+ `(let ((data (truly-the (simple-array ,element-type (*))
+ (%array-data-vector array))))
+ (values data 0 (length data) 0))
+ `(%with-array-data-macro array start end
+ :unsafe? ,(policy node (= safety 0))
+ :element-type ,element-type))))
\f
;;;; array accessors
;; For AREF of vectors we do the bounds checking in the callee. This
;; lets us do a significantly more efficient check for simple-arrays
-;; without bloating the code.
+;; without bloating the code. If we already know the type of the array
+;; with sufficient precision, skip directly to DATA-VECTOR-REF.
(deftransform aref ((array index) (t t) * :node node)
- (if (policy node (zerop insert-array-bounds-checks))
- `(hairy-data-vector-ref array index)
- `(hairy-data-vector-ref/check-bounds array index)))
+ (let ((type (lvar-type array)))
+ (cond ((and (array-type-p type)
+ (null (array-type-complexp type))
+ (not (eql (extract-upgraded-element-type array)
+ *wild-type*))
+ (eql (length (array-type-dimensions type)) 1))
+ `(data-vector-ref array (%check-bound array
+ (array-dimension array 0)
+ index)))
+ ((policy node (zerop insert-array-bounds-checks))
+ `(hairy-data-vector-ref array index))
+ (t
+ `(hairy-data-vector-ref/check-bounds array index)))))
(deftransform %aset ((array index new-value) (t t t) * :node node)
(if (policy node (zerop insert-array-bounds-checks))
(define hairy-data-vector-set/check-bounds
hairy-data-vector-set (new-value) (*)))
-(deftransform aref ((array index) ((or simple-vector
- (simple-unboxed-array 1))
- index))
- (let ((type (lvar-type array)))
- (unless (array-type-p type)
- ;; Not an exactly specified one-dimensional simple array -> punt
- ;; to the complex version.
- (give-up-ir1-transform)))
- `(data-vector-ref array (%check-bound array
- (array-dimension array 0)
- index)))
-
;;; Just convert into a HAIRY-DATA-VECTOR-REF (or
;;; HAIRY-DATA-VECTOR-SET) after checking that the index is inside the
;;; array total size.