(arg-vals n-context)
(arg-vals n-count))
+ ;; The reason for all the noise with
+ ;; STACK-GROWS-DOWNWARD-NOT-UPWARD is to enable generation of
+ ;; slightly more efficient code on x86oid processors. (We can
+ ;; hoist the negation of the index outside the main parsing loop
+ ;; and take advantage of the base+index+displacement addressing
+ ;; mode on x86oids.)
(when (optional-dispatch-keyp res)
(let ((n-index (gensym "N-INDEX-"))
(n-key (gensym "N-KEY-"))
(policy *lexenv* (zerop safety))))
(found-allow-p nil))
- (temps `(,n-index (1- ,n-count)) n-key n-value-temp)
- (body `(declare (fixnum ,n-index) (ignorable ,n-key ,n-value-temp)))
+ (temps #!-stack-grows-downward-not-upward
+ `(,n-index (1- ,n-count))
+ #!+stack-grows-downward-not-upward
+ `(,n-index (- (1- ,n-count)))
+ #!-stack-grows-downward-not-upward n-value-temp
+ #!-stack-grows-downward-not-upward n-key)
+ (body `(declare (fixnum ,n-index)
+ #!-stack-grows-downward-not-upward
+ (ignorable ,n-value-temp ,n-key)))
(collect ((tests))
(dolist (key keys)
(%odd-key-args-error)))
(body
+ #!-stack-grows-downward-not-upward
`(locally
(declare (optimize (safety 0)))
(loop
(decf ,n-index)
(setq ,n-key (%more-arg ,n-context ,n-index))
(decf ,n-index)
- (cond ,@(tests)))))
+ (cond ,@(tests))))
+ #!+stack-grows-downward-not-upward
+ `(locally (declare (optimize (safety 0)))
+ (loop
+ (when (plusp ,n-index) (return))
+ (multiple-value-bind (,n-value-temp ,n-key)
+ (%more-kw-arg ,n-context ,n-index)
+ (declare (ignorable ,n-value-temp ,n-key))
+ (incf ,n-index 2)
+ (cond ,@(tests))))))
(unless allowp
(body `(when (and ,n-losep (not ,n-allowp))
(declare (type optional-dispatch res)
(list default-vars default-vals entry-vars entry-vals vars body
aux-vars aux-vals))
+ (aver (or debug-name (neq '.anonymous. source-name)))
(cond ((not vars)
(if (optional-dispatch-keyp res)
;; Handle &KEY with no keys...
;;; call IR1-CONVERT-HAIRY-ARGS to do the work. When it is done, we
;;; figure out the MIN-ARGS and MAX-ARGS.
(defun ir1-convert-hairy-lambda (body vars keyp allowp aux-vars aux-vals
- &key
- post-binding-lexenv
- (source-name '.anonymous.)
- (debug-name
- (debug-name '&optional-dispatch vars)))
+ &key post-binding-lexenv
+ (source-name '.anonymous.)
+ debug-name)
(declare (list body vars aux-vars aux-vals))
+ (aver (or debug-name (neq '.anonymous. source-name)))
(let ((res (make-optional-dispatch :arglist vars
:allowp allowp
:keyp keyp
:%source-name source-name
- :%debug-name debug-name
+ :%debug-name (debug-name '&optional-dispatch
+ (or debug-name source-name))
:plist `(:ir1-environment
(,*lexenv*
,*current-path*))))
;;; Convert a LAMBDA form into a LAMBDA leaf or an OPTIONAL-DISPATCH leaf.
(defun ir1-convert-lambda (form &key (source-name '.anonymous.)
- debug-name)
+ debug-name maybe-add-debug-catch)
(unless (consp form)
(compiler-error "A ~S was found when expecting a lambda expression:~% ~S"
(type-of form)
(compiler-error
"The lambda expression has a missing or non-list lambda list:~% ~S"
form))
-
+ (unless (or debug-name (neq '.anonymous. source-name))
+ (setf debug-name (name-lambdalike form)))
(multiple-value-bind (vars keyp allow-other-keys aux-vars aux-vals)
(make-lambda-vars (cadr form))
(multiple-value-bind (forms decls) (parse-body (cddr form))
(binding* (((*lexenv* result-type post-binding-lexenv)
(process-decls decls (append aux-vars vars) nil
:binding-form-p t))
- (forms (if (and *allow-instrumenting*
- (policy *lexenv* (>= insert-debug-catch 2)))
- `((catch (locally
- (declare (optimize (insert-step-conditions 0)))
- ;; Using MAKE-SYMBOL would lead
- ;; to recursive disaster.
- (%make-symbol "SB-DEBUG-CATCH-TAG"))
- ,@forms))
+ (debug-catch-p (and maybe-add-debug-catch
+ *allow-instrumenting*
+ (policy *lexenv*
+ (>= insert-debug-catch 2))))
+ (forms (if debug-catch-p
+ (wrap-forms-in-debug-catch forms)
forms))
(forms (if (eq result-type *wild-type*)
forms
(setf (functional-arg-documentation res) (cadr form))
res))))
+(defun wrap-forms-in-debug-catch (forms)
+ #!+unwind-to-frame-and-call-vop
+ `((multiple-value-prog1
+ (progn
+ ,@forms)
+ ;; Just ensure that there won't be any tail-calls, IR2 magic will
+ ;; handle the rest.
+ (values)))
+ #!-unwind-to-frame-and-call-vop
+ `( ;; Normally, we'll return from this block with the below RETURN-FROM.
+ (block
+ return-value-tag
+ ;; If DEBUG-CATCH-TAG is thrown (with a thunk as the value) the
+ ;; RETURN-FROM is elided and we funcall the thunk instead. That
+ ;; thunk might either return a value (for a RETURN-FROM-FRAME)
+ ;; or call this same function again (for a RESTART-FRAME).
+ ;; -- JES, 2007-01-09
+ (funcall
+ (the function
+ ;; Use a constant catch tag instead of consing a new one for every
+ ;; entry to this block. The uniquencess of the catch tags is
+ ;; ensured when the tag is throw by the debugger. It'll allocate a
+ ;; new tag, and modify the reference this tag in the proper
+ ;; catch-block structure to refer to that new tag. This
+ ;; significantly decreases the runtime cost of high debug levels.
+ ;; -- JES, 2007-01-09
+ (catch 'debug-catch-tag
+ (return-from return-value-tag
+ (progn
+ ,@forms))))))))
+
;;; helper for LAMBDA-like things, to massage them into a form
;;; suitable for IR1-CONVERT-LAMBDA.
(defun ir1-convert-lambdalike (thing
&key
(source-name '.anonymous.)
debug-name)
+ (when (and (not debug-name) (eq '.anonymous. source-name))
+ (setf debug-name (name-lambdalike thing)))
(ecase (car thing)
((lambda)
(ir1-convert-lambda thing
+ :maybe-add-debug-catch t
:source-name source-name
:debug-name debug-name))
((instance-lambda)
(if (legal-fun-name-p name)
(let ((defined-fun-res (get-defined-fun name))
(res (ir1-convert-lambda lambda-expression
+ :maybe-add-debug-catch t
:source-name name)))
(assert-global-function-definition-type name res)
(setf (defined-fun-functional defined-fun-res) res)
(policy ref (> recognize-self-calls 0)))
res defined-fun-res))
res)
- (ir1-convert-lambda lambda-expression :debug-name name))))
+ (ir1-convert-lambda lambda-expression
+ :maybe-add-debug-catch t
+ :debug-name name))))
((lambda-with-lexenv)
(ir1-convert-inline-lambda thing
:source-name source-name
;;; current compilation policy. Note that FUN may be a
;;; LAMBDA-WITH-LEXENV, so we may have to augment the environment to
;;; reflect the state at the definition site.
-(defun ir1-convert-inline-lambda (fun
+(defun ir1-convert-inline-lambda (fun
&key
(source-name '.anonymous.)
debug-name
system-lambda)
+ (when (and (not debug-name) (eq '.anonymous. source-name))
+ (setf debug-name (name-lambdalike fun)))
(destructuring-bind (decls macros symbol-macros &rest body)
- (if (eq (car fun) 'lambda-with-lexenv)
- (cdr fun)
- `(() () () . ,(cdr fun)))
- (let ((*lexenv* (make-lexenv
- :default (process-decls decls nil nil
- :lexenv (make-null-lexenv))
- :vars (copy-list symbol-macros)
- :funs (mapcar (lambda (x)
- `(,(car x) .
- (macro . ,(coerce (cdr x) 'function))))
- macros)
- :policy (lexenv-policy *lexenv*)))
- (*allow-instrumenting* (and (not system-lambda) *allow-instrumenting*)))
- (ir1-convert-lambda `(lambda ,@body)
- :source-name source-name
- :debug-name debug-name))))
+ (if (eq (car fun) 'lambda-with-lexenv)
+ (cdr fun)
+ `(() () () . ,(cdr fun)))
+ (let* ((*lexenv* (make-lexenv
+ :default (process-decls decls nil nil
+ :lexenv (make-null-lexenv))
+ :vars (copy-list symbol-macros)
+ :funs (mapcar (lambda (x)
+ `(,(car x) .
+ (macro . ,(coerce (cdr x) 'function))))
+ macros)
+ ;; Inherit MUFFLE-CONDITIONS from the call-site lexenv
+ ;; rather than the definition-site lexenv, since it seems
+ ;; like a much more common case.
+ :handled-conditions (lexenv-handled-conditions *lexenv*)
+ :policy (lexenv-policy *lexenv*)))
+ (*allow-instrumenting* (and (not system-lambda)
+ *allow-instrumenting*))
+ (clambda (ir1-convert-lambda `(lambda ,@body)
+ :source-name source-name
+ :debug-name debug-name)))
+ (setf (functional-inline-expanded clambda) t)
+ clambda)))
;;; Get a DEFINED-FUN object for a function we are about to define. If
;;; the function has been forward referenced, then substitute for the
(unless (eq inlinep :inline)
(setf (defined-fun-inline-expansion var) nil))
(let ((fun (ir1-convert-inline-lambda expansion
- :source-name name
+ :source-name name
;; prevent instrumentation of
;; known function expansions
:system-lambda (and info t))))