X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fphysenvanal.lisp;h=2ded90095178c306d2df2c2f4e4aa6c6f7ee695b;hb=148e3820ad314a9b59d0133c1d60eaac4af9118b;hp=e319ef811810d99a3d6735fd08798df88f4c9b24;hpb=1c2d2fa984c9d0bf07b5a1e5eeae2eade5cc4cb4;p=sbcl.git diff --git a/src/compiler/physenvanal.lisp b/src/compiler/physenvanal.lisp index e319ef8..2ded900 100644 --- a/src/compiler/physenvanal.lisp +++ b/src/compiler/physenvanal.lisp @@ -30,10 +30,10 @@ (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)) @@ -171,11 +171,22 @@ (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 @@ -229,7 +240,7 @@ ;;; ;;; 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. @@ -263,12 +274,12 @@ ;;; 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 +;;; -- 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 ;;; 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 @@ -280,26 +291,23 @@ (let ((entry (exit-entry exit)) (cont (node-cont exit)) (exit-fun (node-home-lambda exit))) - (if (find-nlx-info entry cont) (let ((block (node-block exit))) (aver (= (length (block-succ block)) 1)) (unlink-blocks block (first (block-succ block))) (link-blocks block (component-tail (block-component block)))) (insert-nlx-entry-stub exit env)) - (let ((info (find-nlx-info entry cont))) (aver info) (close-over info (node-physenv exit) env) (when (eq (functional-kind exit-fun) :escape) - (mapc #'(lambda (x) - (setf (node-derived-type x) *wild-type*)) + (mapc (lambda (x) + (setf (node-derived-type x) *wild-type*)) (leaf-refs exit-fun)) (substitute-leaf (find-constant info) exit-fun) (let ((node (block-last (nlx-info-target info)))) (delete-continuation-use node) (add-continuation-use node (nlx-info-continuation info)))))) - (values)) ;;; Iterate over the EXITs in COMPONENT, calling NOTE-NON-LOCAL-EXIT @@ -312,11 +320,10 @@ (dolist (lambda (component-lambdas component)) (dolist (entry (lambda-entries lambda)) (dolist (exit (entry-exits entry)) - (let ((target-env (node-physenv entry))) - (if (eq (node-physenv exit) target-env) + (let ((target-physenv (node-physenv entry))) + (if (eq (node-physenv exit) target-physenv) (maybe-delete-exit exit) - (note-non-local-exit target-env exit)))))) - + (note-non-local-exit target-physenv exit)))))) (values)) ;;;; cleanup emission @@ -326,7 +333,10 @@ ;;; in an implicit MV-PROG1. We have to force local call analysis of ;;; new references to UNWIND-PROTECT cleanup functions. If we don't ;;; actually have to do anything, then we don't insert any cleanup -;;; code. +;;; code. (FIXME: There's some confusion here, left over from CMU CL +;;; comments. CLEANUP1 isn't mentioned in the code of this function. +;;; It is in code elsewhere, but if the comments for this function +;;; mention it they should explain the relationship to the other code.) ;;; ;;; If we do insert cleanup code, we check that BLOCK1 doesn't end in ;;; a "tail" local call. @@ -392,20 +402,29 @@ (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))