1.0.36.5: delay transforms for SLOT-VALUE and (SETF SLOT-VALUE)
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 28 Feb 2010 19:05:39 +0000 (19:05 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 28 Feb 2010 19:05:39 +0000 (19:05 +0000)
 Fixes launchpad bug #520366

NEWS
src/pcl/fixup.lisp
tests/clos.impure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index 2d74cd5..8cb4f36 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@
 changes relative to sbcl-1.0.36:
   * enhancement: Backtrace from THROW to uncaught tag on x86oids now shows
     stack frame thrown from.
+  * optimization: SLOT-VALUE and (SETF SLOT-VALUE) take advantage of
+    constraint propgation, allowing better compilation eg. when used to
+    access structures with WITH-SLOTS. (lp#520366)
   * bug fix: Fix compiler error involving MAKE-ARRAY and IF forms
     in :INITIAL-CONTENTS. (lp#523612)
   * bug fix: FUNCTION-LAMBDA-EXPRESSION lost declarations from interpreted
index e544e0b..d4e0257 100644 (file)
@@ -43,7 +43,8 @@
 (defknown slot-value (t symbol) t (any))
 (defknown sb-pcl::set-slot-value (t symbol t) t (any))
 
-(deftransform slot-value ((object slot-name) (t (constant-arg symbol)))
+(deftransform slot-value ((object slot-name) (t (constant-arg symbol)) *
+                          :node node)
   (let ((c-slot-name (lvar-value slot-name)))
     (if (sb-pcl::interned-symbol-p c-slot-name)
         (let* ((type (lvar-type object))
                       (sb-kernel::structure-classoid-name type))))
                (dsd (when dd
                       (find c-slot-name (dd-slots dd) :key #'dsd-name))))
-          (if dsd
-              `(,(dsd-accessor-name dsd) object)
-              `(sb-pcl::accessor-slot-value object ',c-slot-name)))
+          (cond (dsd
+                 `(,(dsd-accessor-name dsd) object))
+                (t
+                 (delay-ir1-transform node :constraint)
+                 `(sb-pcl::accessor-slot-value object ',c-slot-name))))
         (give-up-ir1-transform "slot name is not an interned symbol"))))
 
 (deftransform sb-pcl::set-slot-value ((object slot-name new-value)
                       (sb-kernel::structure-classoid-name type))))
                (dsd (when dd
                       (find c-slot-name (dd-slots dd) :key #'dsd-name))))
-          (if dsd
-              `(setf (,(dsd-accessor-name dsd) object) new-value)
-              (if (policy node (= safety 3))
-                  ;; Safe code wants to check the type, and the global
-                  ;; accessor won't do that. Also see the comment in the
-                  ;; compiler-macro.
-                  (give-up-ir1-transform "cannot use optimized accessor in safe code")
-                  `(sb-pcl::accessor-set-slot-value object ',c-slot-name new-value))))
+          (cond (dsd
+                 `(setf (,(dsd-accessor-name dsd) object) new-value))
+                ((policy node (= safety 3))
+                 ;; Safe code wants to check the type, and the global
+                 ;; accessor won't do that. Also see the comment in the
+                 ;; compiler-macro.
+                 (give-up-ir1-transform "cannot use optimized accessor in safe code"))
+                (t
+                 (delay-ir1-transform node :constraint)
+                 `(sb-pcl::accessor-set-slot-value object ',c-slot-name new-value))))
         (give-up-ir1-transform "slot name is not an interned symbol"))))
index 7a313b9..b0f0490 100644 (file)
@@ -11,8 +11,9 @@
 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
 ;;;; more information.
 
+(load "compiler-test-util.lisp")
 (defpackage "CLOS-IMPURE"
-  (:use "CL" "ASSERTOID" "TEST-UTIL"))
+  (:use "CL" "ASSERTOID" "TEST-UTIL" "COMPILER-TEST-UTIL"))
 (in-package "CLOS-IMPURE")
 \f
 ;;; It should be possible to do DEFGENERIC and DEFMETHOD referring to
     bug-485019)
   (bug-485019 (make-instance 'bug-485019)))
 
+;;; The compiler didn't propagate the declarared type before applying
+;;; the transform for (SETF SLOT-VALUE), so the generic accessor was used.
+(defstruct foo-520366
+  slot)
+(defun quux-520366 (cont)
+  (funcall cont))
+(defun bar-520366 (foo-struct)
+  (declare (type foo-520366 foo-struct))
+  (with-slots (slot) foo-struct
+    (tagbody
+       (quux-520366 #'(lambda ()
+                        (setf slot :value)
+                        (go TAG)))
+     TAG)))
+(with-test (:name :bug-520366)
+  (let ((callees (find-named-callees #'bar-520366)))
+    (assert (equal (list #'quux) callees))))
+
 ;;;; success
index 4ccec24..f34d9ad 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.36.4"
+"1.0.36.5"