+;; 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. 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)
+ (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))
+ `(hairy-data-vector-set array index new-value)
+ `(hairy-data-vector-set/check-bounds array index new-value)))
+
+;;; But if we find out later that there's some useful type information
+;;; available, switch back to the normal one to give other transforms
+;;; a stab at it.
+(macrolet ((define (name transform-to extra extra-type)
+ `(deftransform ,name ((array index ,@extra))
+ (let ((type (lvar-type array))
+ (element-type (extract-upgraded-element-type array)))
+ ;; If an element type has been declared, we want to
+ ;; use that information it for type checking (even
+ ;; if the access can't be optimized due to the array
+ ;; not being simple).
+ (when (and (eql element-type *wild-type*)
+ ;; This type logic corresponds to the special
+ ;; case for strings in HAIRY-DATA-VECTOR-REF
+ ;; (generic/vm-tran.lisp)
+ (not (csubtypep type (specifier-type 'simple-string))))
+ (when (or (not (array-type-p type))
+ ;; If it's a simple array, we might be able
+ ;; to inline the access completely.
+ (not (null (array-type-complexp type))))
+ (give-up-ir1-transform
+ "Upgraded element type of array is not known at compile time."))))
+ `(,',transform-to array
+ (%check-bound array
+ (array-dimension array 0)
+ index)
+ ,@',extra))))
+ (define hairy-data-vector-ref/check-bounds
+ hairy-data-vector-ref nil nil)
+ (define hairy-data-vector-set/check-bounds
+ hairy-data-vector-set (new-value) (*)))
+