;;; 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)))
- (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))
;;;
;;; 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
(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))
`(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)))))))))
(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))
;;; Attempt to convert a call to a lambda. If the number of args is
(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)))))))
(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)
(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))
;; 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
(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.
;;; 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))
(let ((result (return-result return))
(cont (node-cont call))
(call-type (node-derived-type call)))
- (when (eq (continuation-use cont) call)
- (assert-continuation-type cont (continuation-asserted-type 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))
(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))
;; 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