0.8.1.40:
[sbcl.git] / src / compiler / physenvanal.lisp
index 531e080..1da7274 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))
 
 ;;; If FUN has no physical environment, assign one, otherwise clean up
 ;;; the old physical environment, removing/flagging variables that
 ;;; have no sets or refs. If a var has no references, we remove it
-;;; from the closure. If it has no sets, we clear the INDIRECT flag.
-;;; This is necessary because pre-analysis is done before
-;;; optimization.
+;;; from the closure. We always clear the INDIRECT flag. This is
+;;; necessary because pre-analysis is done before optimization.
 (defun reinit-lambda-physenv (fun)
   (let ((old (lambda-physenv (lambda-home fun))))
     (cond (old
                            (physenv-closure old)))
           (flet ((clear (fun)
                    (dolist (var (lambda-vars fun))
-                     (unless (lambda-var-sets var)
-                       (setf (lambda-var-indirect var) nil)))))
+                     (setf (lambda-var-indirect var) nil))))
             (clear fun)
             (map nil #'clear (lambda-lets fun))))
          (t
 
          (let ((set-physenv (get-node-physenv set)))
            (unless (eq set-physenv physenv)
-             (setf did-something t
+              (setf did-something t
                    (lambda-var-indirect var) t)
              (close-over var set-physenv physenv))))))
     did-something))
 ;;;
 ;;; 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)
+           (when (and (policy use merge-tail-calls)
+                      (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)))))))
+             (setf (node-tail-p use) t)))))))
   (values))