1.0.42.15: prevent inline expansion from creating refs to dead lambda-vars
authorNikodemus Siivola <nikodemus@random-state.net>
Wed, 1 Sep 2010 14:42:09 +0000 (14:42 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Wed, 1 Sep 2010 14:42:09 +0000 (14:42 +0000)
 * Fixes lp#454681.

 * Patch by Alexey. In his words, in reference to the test-case:

   (multiple-value-bind (iterator+977 getter+978)
       (does-not-exist-but-does-not-matter)
     (flet ((iterator+976 ()
              (funcall iterator+977)))
       (declare (inline iterator+976))
       (let ((iterator+976 #'iterator+976))
         (funcall iterator+976)))))

   Inline expansion of ITERATOR+976 tries to refer to a dead
   LAMBDA-VAR ITERATOR+977 of varargs entry, which was substituted
   with ITERATOR+977 of &OPTIONAL processor. Thus the referenced
   variable is dead and is not bound anywhere.

   The attached patch fixes the problem by giving up on inline
   expansion if it tries to make a reference to a dead LAMBDA-VAR,
   similar to the way dead BLOCK tags are treated.

NEWS
src/compiler/ir1tran.lisp
src/compiler/ir1util.lisp
src/compiler/node.lisp
tests/compiler.pure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index 7590b59..16dbb31 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,8 @@ changes relative to sbcl-1.0.42
     (lp#544421)
   * bug fix: legally dynamic-extent lists and vectors used as
     initialization arguments to MAKE-ARRAY can be stack allocated. (lp#586105)
+  * bug fix: inline-expansion creating references to dead lambda-variables
+    (lp#454681, thanks to Alexey Dejneka)
 
 changes in sbcl-1.0.42 relative to sbcl-1.0.41
   * build changes
index 728a23a..a18ca2a 100644 (file)
 ;;; functional instead.
 (defun reference-leaf (start next result leaf &optional (name '.anonymous.))
   (declare (type ctran start next) (type (or lvar null) result) (type leaf leaf))
-  (when (functional-p leaf)
-    (assure-functional-live-p leaf))
+  (assure-leaf-live-p leaf)
   (let* ((type (lexenv-find leaf type-restrictions))
          (leaf (or (and (defined-fun-p leaf)
                         (not (eq (defined-fun-inlinep leaf)
index 6641386..aeb2566 100644 (file)
 (defun delete-lambda-var (leaf)
   (declare (type lambda-var leaf))
 
+  (setf (lambda-var-deleted leaf) t)
   ;; Iterate over all local calls flushing the corresponding argument,
   ;; allowing the computation of the argument to be deleted. We also
   ;; mark the LET for reoptimization, since it may be that we have
@@ -2035,6 +2036,15 @@ is :ANY, the function name is not checked."
               (memq (functional-kind functional) '(:deleted :zombie))))
     (throw 'locall-already-let-converted functional)))
 
+(defun assure-leaf-live-p (leaf)
+  (typecase leaf
+    (lambda-var
+     (when (lambda-var-deleted leaf)
+       (throw 'locall-already-let-converted leaf)))
+    (functional
+     (assure-functional-live-p leaf))))
+
+
 (defun call-full-like-p (call)
   (declare (type combination call))
   (let ((kind (basic-combination-kind call)))
index 41964ad..5229904 100644 (file)
   ;; This is set by physical environment analysis if it chooses an
   ;; indirect (value cell) representation for this variable because it
   ;; is both set and closed over.
-  indirect)
+  indirect
+  ;; true if the last reference has been deleted (and new references
+  ;; should not be made)
+  deleted
+  )
 
 (def!struct (lambda-var (:include basic-var))
   (flags (lambda-var-attributes)
   `(lambda-var-attributep (lambda-var-flags ,var) ignore))
 (defmacro lambda-var-indirect (var)
   `(lambda-var-attributep (lambda-var-flags ,var) indirect))
+(defmacro lambda-var-deleted (var)
+  `(lambda-var-attributep (lambda-var-flags ,var) deleted))
 \f
 ;;;; basic node types
 
index 19640d9..8be6ff1 100644 (file)
 
 (with-test (:name :dotimes-non-integer-counter-value)
   (assert (raises-error? (dotimes (i 8.6)) type-error)))
+
+(with-test (:name :bug-454681)
+  ;; This used to break due to reference to a dead lambda-var during
+  ;; inline expansion.
+  (assert (compile nil
+                   `(lambda ()
+                      (multiple-value-bind (iterator+977 getter+978)
+                          (does-not-exist-but-does-not-matter)
+                        (flet ((iterator+976 ()
+                                 (funcall iterator+977)))
+                          (declare (inline iterator+976))
+                          (let ((iterator+976 #'iterator+976))
+                            (funcall iterator+976))))))))
index e552d0a..7382b6f 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.42.14"
+"1.0.42.15"