X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Flocall.lisp;h=bf6c409fb1d257dbc8fab41f7befd27d03cf8b90;hb=f1407e424f1063203af07d2e61ceef58515a4797;hp=304142d62f55023f9534e3f34be1f08ef1186e7e;hpb=7ce2c42adf3d62f03086de940adaee48e6161a40;p=sbcl.git diff --git a/src/compiler/locall.lisp b/src/compiler/locall.lisp index 304142d..bf6c409 100644 --- a/src/compiler/locall.lisp +++ b/src/compiler/locall.lisp @@ -34,17 +34,14 @@ ;;; continuations. (defun propagate-to-args (call fun) (declare (type combination call) (type clambda fun)) - (do ((args (basic-combination-args call) (cdr args)) - (vars (lambda-vars fun) (cdr vars))) - ((null args)) - (let ((arg (car args)) - (var (car vars))) - (cond ((leaf-refs var) - (assert-continuation-type arg (leaf-type var) - (lexenv-policy (node-lexenv call)))) - (t - (flush-dest arg) - (setf (car args) nil))))) + (loop with policy = (lexenv-policy (node-lexenv call)) + for args on (basic-combination-args call) + and var in (lambda-vars fun) + for arg = (assert-continuation-type (car args) + (leaf-type var) policy) + do (unless (leaf-refs var) + (flush-dest (car args)) + (setf (car args) nil))) (values)) @@ -112,9 +109,9 @@ ;;; ;;; If there is a &MORE arg, then there are a couple of optimizations ;;; that we make (more for space than anything else): -;;; -- If MIN-ARGS is 0, then we make the more entry a T clause, since +;;; -- If MIN-ARGS is 0, then we make the more entry a T clause, since ;;; no argument count error is possible. -;;; -- We can omit the = clause for the last entry-point, allowing the +;;; -- We can omit the = clause for the last entry-point, allowing the ;;; case of 0 more args to fall through to the more entry. ;;; ;;; We don't bother to policy conditionalize wrong arg errors in @@ -134,21 +131,11 @@ (temps (make-gensym-list (length (lambda-vars fun))))) `(lambda (,n-supplied ,@temps) (declare (type index ,n-supplied)) - ,(if (policy *lexenv* (zerop safety)) + ,(if (policy *lexenv* (zerop verify-arg-count)) `(declare (ignore ,n-supplied)) `(%verify-arg-count ,n-supplied ,nargs)) (locally - ;; KLUDGE: The intent here is to enable tail recursion - ;; optimization, since leaving frames for wrapper - ;; functions like this on the stack is actually more - ;; annoying than helpful for debugging. Unfortunately - ;; trying to express this by messing with the - ;; ANSI-standard declarations is a little awkward, since - ;; no matter how we do it we'll tend to have side-effects - ;; on things like SPEED-vs.-SAFETY comparisons. Perhaps - ;; it'd be better to define a new SB-EXT:TAIL-RECURSIVELY - ;; declaration and use that? -- WHN 2002-07-08 - (declare (optimize (speed 2) (debug 1))) + (declare (optimize (merge-tail-calls 3))) (%funcall ,fun ,@temps))))) (optional-dispatch (let* ((min (optional-dispatch-min-args fun)) @@ -176,11 +163,7 @@ `(multiple-value-bind (,n-context ,n-count) (%more-arg-context ,n-supplied ,max) (locally - ;; KLUDGE: As above, we're trying to - ;; enable tail recursion optimization and - ;; any other effects of this declaration - ;; are accidental. -- WHN 2002-07-08 - (declare (optimize (speed 2) (debug 1))) + (declare (optimize (merge-tail-calls 3))) (%funcall ,more ,@temps ,n-context ,n-count))))))) (t (%arg-count-error ,n-supplied))))))))) @@ -456,8 +439,7 @@ (assert-continuation-type (first (basic-combination-args call)) - (make-values-type :optional (mapcar #'leaf-type (lambda-vars ep)) - :rest *universal-type*) + (make-short-values-type (mapcar #'leaf-type (lambda-vars ep))) (lexenv-policy (node-lexenv call))))) (values)) @@ -547,8 +529,8 @@ (with-ir1-environment-from-node call (ir1-convert-lambda `(lambda ,vars - (declare (ignorable . ,ignores)) - (%funcall ,entry . ,args)) + (declare (ignorable ,@ignores)) + (%funcall ,entry ,@args)) :debug-name (debug-namify "hairy function entry ~S" (continuation-fun-name (basic-combination-fun call))))))) @@ -651,7 +633,7 @@ (collect ((call-args)) (do ((var arglist (cdr var)) (temp temps (cdr temp))) - (()) + ((null var)) (let ((info (lambda-var-arg-info (car var)))) (if info (ecase (arg-info-kind info) @@ -722,7 +704,7 @@ (join-components component clambda-component))) (let ((*current-component* component)) (node-ends-block call)) - ;; FIXME: Use DESTRUCTURING-BIND here, and grep for other + ;; FIXME: Use DESTRUCTURING-BIND here, and grep for other ;; uses of '=.*length' which could also be converted to use ;; DESTRUCTURING-BIND or PROPER-LIST-OF-LENGTH-P. (aver (= (length (block-succ call-block)) 1)) @@ -781,10 +763,10 @@ ;; information. (setf (tail-set-info (lambda-tail-set clambda)) nil)) -;;; Handle the environment semantics of LET conversion. We add CLAMBDA -;;; and its LETs to LETs for the CALL's home function. We merge the -;;; calls for CLAMBDA with the calls for the home function, removing -;;; CLAMBDA in the process. We also merge the ENTRIES. +;;; Handle the PHYSENV semantics of LET conversion. We add CLAMBDA and +;;; its LETs to LETs for the CALL's home function. We merge the calls +;;; for CLAMBDA with the calls for the home function, removing CLAMBDA +;;; in the process. We also merge the ENTRIES. ;;; ;;; We also unlink the function head from the component head and set ;;; COMPONENT-REANALYZE to true to indicate that the DFO should be @@ -803,20 +785,20 @@ (depart-from-tail-set clambda) (let* ((home (node-home-lambda call)) - (home-env (lambda-physenv home))) + (home-physenv (lambda-physenv home))) (aver (not (eq home clambda))) ;; CLAMBDA belongs to HOME now. (push clambda (lambda-lets home)) (setf (lambda-home clambda) home) - (setf (lambda-physenv clambda) home-env) + (setf (lambda-physenv clambda) home-physenv) ;; All of CLAMBDA's LETs belong to HOME now. (let ((lets (lambda-lets clambda))) (dolist (let lets) (setf (lambda-home let) home) - (setf (lambda-physenv let) home-env)) + (setf (lambda-physenv let) home-physenv)) (setf (lambda-lets home) (nconc lets (lambda-lets home)))) ;; CLAMBDA no longer has an independent existence as an entity ;; which has LETs. @@ -846,15 +828,6 @@ ;;; node, and change the control flow to transfer to NEXT-BLOCK ;;; instead. Move all the uses of the result continuation to CALL's ;;; CONT. -;;; -;;; If the actual continuation is only used by the LET call, then we -;;; intersect the type assertion on the dummy continuation with the -;;; assertion for the actual continuation; in all other cases -;;; assertions on the dummy continuation are lost. -;;; -;;; We also intersect the derived type of the CALL with the derived -;;; type of all the dummy continuation's uses. This serves mainly to -;;; propagate TRULY-THE through LETs. (defun move-return-uses (fun call next-block) (declare (type clambda fun) (type basic-combination call) (type cblock next-block)) @@ -868,13 +841,9 @@ (let ((result (return-result return)) (cont (node-cont call)) (call-type (node-derived-type call))) - (when (eq (continuation-use cont) call) - (set-continuation-type-assertion - cont - (continuation-asserted-type result) - (continuation-type-to-check result))) (unless (eq call-type *wild-type*) - (do-uses (use result) + ;; FIXME: Replace the call with unsafe CAST. -- APD, 2002-01-26 + (do-uses (use result) (derive-node-type use call-type))) (substitute-continuation-uses cont result))) (values)) @@ -958,12 +927,25 @@ (cond ((not return)) ((or next-block call-return) (unless (block-delete-p (node-block return)) + (when (and (node-tail-p call) + call-return + (not (eq (node-cont call) + (return-result call-return)))) + ;; We do not care to give a meaningful continuation to + ;; a tail combination, but here we need it. + (delete-continuation-use call) + (add-continuation-use call (return-result call-return))) (move-return-uses fun call - (or next-block (node-block call-return))))) + (or next-block + (let ((block (node-block call-return))) + (when (block-delete-p block) + (setf (block-delete-p block) nil)) + block))))) (t (aver (node-tail-p call)) (setf (lambda-return call-fun) return) - (setf (return-lambda return) call-fun)))) + (setf (return-lambda return) call-fun) + (setf (lambda-return fun) nil)))) (move-let-call-cont fun) (values)) @@ -996,15 +978,16 @@ ;; From the user's point of view, LET-converting something that ;; has a name is inlining it. (The user can't see what we're doing ;; with anonymous things, and suppressing inlining - ;; for such things can easily give Python acute indigestion, so + ;; for such things can easily give Python acute indigestion, so ;; we don't.) (when (leaf-has-source-name-p clambda) ;; ANSI requires that explicit NOTINLINE be respected. (or (eq (lambda-inlinep clambda) :notinline) - ;; If (> DEBUG SPEED) we can guess that inlining generally - ;; won't be appreciated, but if the user specifically requests - ;; inlining, that takes precedence over our general guess. - (and (policy clambda (> debug speed)) + ;; If (= LET-CONVERTION 0) we can guess that inlining + ;; generally won't be appreciated, but if the user + ;; specifically requests inlining, that takes precedence over + ;; our general guess. + (and (policy clambda (= let-convertion 0)) (not (eq (lambda-inlinep clambda) :inline)))))) ;;; We also don't convert calls to named functions which appear in the