Fix (aref vector (+ i constant)) with i negative on x86oids
authorPaul Khuong <pvk@pvk.ca>
Fri, 24 May 2013 17:07:35 +0000 (13:07 -0400)
committerPaul Khuong <pvk@pvk.ca>
Fri, 24 May 2013 18:49:33 +0000 (14:49 -0400)
 * The VOPs for indexed access with constant offset take a fixnum
   index. Adjust fndb entries to reflect that.

 * Fix FOLD-INDEX-ADDRESSING: don't convert if the resulting index
   would be wider than a fixnum, and compute the new offset correctly
   for subtractions.

 * Test case by Douglas Katzman.

NEWS
src/compiler/fndb.lisp
src/compiler/generic/vm-fndb.lisp
src/compiler/generic/vm-tran.lisp
tests/compiler.pure.lisp

diff --git a/NEWS b/NEWS
index a2e9a56..6a36c16 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -73,6 +73,8 @@ changes relative to sbcl-1.1.7:
     about a constant NIL (similar for non-EQ-comparable catch tags).
   * bug fix: Referring to INLINE global functions as values should not result
     in a compilation failure. (lp#1035721)
+  * bug fix: Known-safe vector access on x86oids should not fail spuriously
+    when the index is of the form (+ x constant-positive-integer).
   * optimization: faster ISQRT on fixnums and small bignums
   * optimization: faster and smaller INTEGER-LENGTH on fixnums on x86-64.
   * optimization: On x86-64, the number of multi-byte NOP instructions used
index 1aef68d..5a4e4eb 100644 (file)
   (movable foldable flushable dx-safe))
 (defknown data-vector-ref (simple-array index) t
   (foldable explicit-check always-translatable))
-(defknown data-vector-ref-with-offset (simple-array index fixnum) t
+(defknown data-vector-ref-with-offset (simple-array fixnum fixnum) t
   (foldable explicit-check always-translatable))
 (defknown data-vector-set (array index t) t
   (explicit-check always-translatable))
-(defknown data-vector-set-with-offset (array index fixnum t) t
+(defknown data-vector-set-with-offset (array fixnum fixnum t) t
   (explicit-check always-translatable))
 (defknown hairy-data-vector-ref (array index) t
   (foldable explicit-check))
index 37273c1..003dc37 100644 (file)
 (defknown %bignum-ref (bignum-type bignum-index) bignum-element-type
   (flushable))
 #!+(or x86 x86-64)
-(defknown %bignum-ref-with-offset (bignum-type bignum-index (signed-byte 24))
+(defknown %bignum-ref-with-offset (bignum-type fixnum (signed-byte 24))
   bignum-element-type (flushable always-translatable))
 
 (defknown %bignum-set (bignum-type bignum-index bignum-element-type)
   ())
 #!+(or x86 x86-64)
 (defknown %bignum-set-with-offset
-  (bignum-type bignum-index (signed-byte 24) bignum-element-type)
+  (bignum-type fixnum (signed-byte 24) bignum-element-type)
   bignum-element-type (always-translatable))
 
 (defknown %digit-0-or-plusp (bignum-element-type) boolean
index c4044a3..7984b71 100644 (file)
                               index offset &optional setter-p)
   (multiple-value-bind (func index-args) (extract-fun-args index '(+ -) 2)
     (destructuring-bind (x constant) index-args
-      (declare (ignorable x))
-      (unless (constant-lvar-p constant)
+      (unless (and (constant-lvar-p constant)
+                   ;; the remaining argument must be a fixnum, otherwise we lose
+                   (csubtypep (lvar-type x) (specifier-type 'fixnum)))
+        (delay-ir1-transform :constraint)
         (give-up-ir1-transform))
-      (let ((value (lvar-value constant)))
+      (let ((value (lvar-value constant))
+            new-offset)
         (unless (and (integerp value)
                      (sb!vm::foldable-constant-offset-p
                       element-size lowtag data-offset
-                      (funcall func value (lvar-value offset))))
+                      (setf new-offset (funcall func (lvar-value offset) value))))
           (give-up-ir1-transform "constant is too large for inlining"))
         (splice-fun-args index func 2)
         `(lambda (thing index off1 off2 ,@(when setter-p
                                             '(value)))
-           (,fun-name thing index (,func off2 off1) ,@(when setter-p
-                                                        '(value))))))))
+           (declare (ignore off1 off2))
+           (,fun-name thing index ',new-offset ,@(when setter-p
+                                                   '(value))))))))
 
 #!+(or x86 x86-64)
 (deftransform sb!bignum:%bignum-ref-with-offset
index e16ad55..6ffdf0a 100644 (file)
           (test (- x) y)
           (test (- most-positive-fixnum x) y)
           (test (+ most-negative-fixnum x) y))))))
+
+(test-util:with-test (:name :fold-index-addressing-positive-offset)
+  (let ((f (compile nil `(lambda (i)
+                           (if (typep i '(integer -31 31))
+                               (aref #. (make-array 63) (+ i 31))
+                               (error "foo"))))))
+    (funcall f -31)))