0.7.7.26:
[sbcl.git] / src / compiler / physenvanal.lisp
index c96bd44..2ded900 100644 (file)
   (declare (type component component))
   (aver (every (lambda (x)
                 (eq (functional-kind x) :deleted))
-              (component-new-funs component)))
-  (setf (component-new-funs component) ())
-  (dolist (fun (component-lambdas component))
-    (reinit-lambda-physenv fun))
+              (component-new-functionals component)))
+  (setf (component-new-functionals component) ())
+  (dolist (clambda (component-lambdas component))
+    (reinit-lambda-physenv clambda))
   (mapc #'add-lambda-vars-and-let-vars-to-closures
        (component-lambdas component))
 
            (setq did-something t)
            (close-over var ref-physenv physenv))))
       (dolist (set (basic-var-sets var))
-       (let ((set-physenv (get-node-physenv set)))
-         (unless (eq set-physenv physenv)
-           (setq did-something t)
-           (setf (lambda-var-indirect var) t)
-           (close-over var set-physenv physenv)))))
+
+       ;; Variables which are set but never referenced can be
+       ;; optimized away, and closing over them here would just
+       ;; interfere with that. (In bug 147, it *did* interfere with
+       ;; that, causing confusion later. This UNLESS solves that
+       ;; problem, but I (WHN) am not 100% sure it's best to solve
+       ;; the problem this way instead of somehow solving it
+       ;; somewhere upstream and just doing (AVER (LEAF-REFS VAR))
+       ;; here.)
+       (unless (null (leaf-refs var))
+
+         (let ((set-physenv (get-node-physenv set)))
+           (unless (eq set-physenv physenv)
+             (setf did-something t
+                   (lambda-var-indirect var) t)
+             (close-over var set-physenv physenv))))))
     did-something))
 
 ;;; Find any variables in CLAMBDA -- either directly in LAMBDA-VARS or
 ;;;
 ;;; If a CATCH or an UNWIND-protect, then we set the LEXENV for the
 ;;; last node in the cleanup code to be the enclosing environment, to
-;;; represent the fact that the binding was undone as a side-effect of
+;;; represent the fact that the binding was undone as a side effect of
 ;;; the exit. This will cause a lexical exit to be broken up if we are
 ;;; actually exiting the scope (i.e. a BLOCK), and will also do any
 ;;; other cleanups that may have to be done on the way.
 ;;; EXIT into ENV. This is called for each non-local exit node, of
 ;;; which there may be several per exit continuation. This is what we
 ;;; do:
-;;; -- If there isn't any NLX-Info entry in the environment, make
+;;; -- If there isn't any NLX-INFO entry in the environment, make
 ;;;    an entry stub, otherwise just move the exit block link to
 ;;;    the component tail.
 ;;; -- Close over the NLX-INFO in the exit environment.
 ;;; -- If the exit is from an :ESCAPE function, then substitute a
-;;;    constant reference to NLX-Info structure for the escape
+;;;    constant reference to NLX-INFO structure for the escape
 ;;;    function reference. This will cause the escape function to
 ;;;    be deleted (although not removed from the DFO.)  The escape
 ;;;    function is no longer needed, and we don't want to emit code
              (emit-cleanups block1 block2)))))))
   (values))
 
-;;; Mark all tail-recursive uses of function result continuations with
-;;; the corresponding TAIL-SET. Nodes whose type is NIL (i.e. don't
-;;; return) such as calls to ERROR are never annotated as tail in
-;;; order to preserve debugging information.
+;;; Mark optimizable tail-recursive uses of function result
+;;; continuations with the corresponding TAIL-SET.
 (defun tail-annotate (component)
   (declare (type component component))
   (dolist (fun (component-lambdas component))
     (let ((ret (lambda-return fun)))
+      ;; Nodes whose type is NIL (i.e. don't return) such as calls to
+      ;; ERROR are never annotated as TAIL-P, in order to preserve
+      ;; debugging information.
+      ;;
+      ;; FIXME: It might be better to add another DEFKNOWN property
+      ;; (e.g. NO-TAIL-RECURSION) and use it for error-handling
+      ;; functions like ERROR, instead of spreading this special case
+      ;; net so widely.
       (when ret
        (let ((result (return-result ret)))
          (do-uses (use result)
-           (when (and (immediately-used-p result use)
-                    (or (not (eq (node-derived-type use) *empty-type*))
-                        (not (basic-combination-p use))
-                        (eq (basic-combination-kind use) :local)))
-               (setf (node-tail-p use) t)))))))
+           (when (and (policy use
+                              (or (> space debug)
+                                  (> speed debug)))
+                      (immediately-used-p result use)
+                      (or (not (eq (node-derived-type use) *empty-type*))
+                          (not (basic-combination-p use))
+                          (eq (basic-combination-kind use) :local)))
+             (setf (node-tail-p use) t)))))))
   (values))