so the compiler doesn't compile the type test into code, but
instead just saves the type in a lexical closure and interprets it
at runtime.
- A proper solution involves deciding whether it's really worth
- saving space by implementing structure slot accessors as closures.
- (If it's not worth it, the problem vanishes automatically. If it
- is worth it, there are hacks we could use to force type tests to
- be compiled anyway, and even shared. E.g. we could implement
- an EQUAL hash table mapping from types to compiled type tests,
- and save the appropriate compiled type test as part of each lexical
- closure; or we could make the lexical closures be placeholders
- which overwrite their old definition as a lexical closure with
- a new compiled definition the first time that they're called.)
- As a workaround for the problem, #'(SETF FOO) expressions can
- be replaced with (EFFICIENT-SETF-FUNCTION FOO), where
+ To exercise the problem, compile and load
+ (cl:in-package :cl-user)
+ (defstruct foo
+ (bar (error "missing") :type bar))
+ (defvar *foo*)
+ (defun wastrel1 (x)
+ (loop (setf (foo-bar *foo*) x)))
+ (defstruct bar)
+ (defvar *bar* (make-bar))
+ (defvar *foo* (make-foo :bar *bar*))
+ (defvar *setf-foo-bar* #'(setf foo-bar))
+ (defun wastrel2 (x)
+ (loop (funcall *setf-foo-bar* x *foo*)))
+ then run (WASTREL1 *BAR*) or (WASTREL2 *BAR*), hit Ctrl-C, and
+ use BACKTRACE, to see it's spending all essentially all its time
+ in %TYPEP and VALUES-SPECIFIER-TYPE and so forth.
+ One possible solution would be simply to give up on
+ representing structure slot accessors as functions, and represent
+ them as macroexpansions instead. This can be inconvenient for users,
+ but it's not clear that it's worse than trying to help by expanding
+ into a horribly inefficient implementation.
+ As a workaround for the problem, #'(SETF FOO) expressions
+ can be replaced with (EFFICIENT-SETF-FUNCTION FOO), where
(defmacro efficient-setf-function (place-function-name)
(or #+sbcl (and (sb-int:info :function :accessor-for place-function-name)
;; a workaround for the problem, encouraging the
elif [ -x "`which gmake`" ] ; then
# "gmake" is the preferred name in *BSD.
GNUMAKE=gmake
-else
- # FIXME: Now that we do this early, maybe prompt the user rather
- # than guessing? I'd still be annoyed, though... -- CSR,
- # 2003-05-16.
- #
- # All the world's a Linux, and all its users weary of cautious
- # BSDish worries that "make" might not be GNU make; so just guess
- # that "make" is GNU make and hope for the best.
+elif [ "GNU Make" = "`make -v | head -n 1 | cut -b 0-8`" ]; then
GNUMAKE=make
+else
+ echo "GNU Make not found. Try setting the environment variable GNUMAKE."
+ exit 1
fi
export GNUMAKE
`(,operator ,@(mapcar (lambda (m) `(call-method ,m ()))
primary)))))
(cond ((null primary)
- `(error "No ~S methods for the generic function ~S."
- ',type ',generic-function))
+ ;; FIXME(?): NO-APPLICABLE-METHOD seems more appropriate
+ ;; here, but
+ ;; (1) discussion with CSR on #lisp reminded me that it's
+ ;; a vexed question whether we can validly call
+ ;; N-A-M when an :AROUND method exists (and the
+ ;; definition of NO-NEXT-METHOD seems to discourage
+ ;; us from calling NO-NEXT-METHOD directly in that
+ ;; case, since it's supposed to be called from a
+ ;; CALL-NEXT-METHOD form), and
+ ;; (2) a call to N-A-M would require &REST FUN-ARGS, and
+ ;; we don't seem to have FUN-ARGS here.
+ ;; I think ideally failures in short method combination
+ ;; would end up either in NO-APPLICABLE-METHOD or
+ ;; NO-NEXT-METHOD, and I expect that's what ANSI
+ ;; generally intended, but it's not clear to me whether
+ ;; the details of what they actually specified let us
+ ;; make that happen. So for now I've just tried to
+ ;; clarify the error message text but left the general
+ ;; logic alone (and raised the question on sbcl-devel).
+ ;; -- WHN 2003-06-16
+ `(error "no ~S methods for ~S on these arguments"
+ ',type
+ ',generic-function))
((null around) main-method)
(t
`(call-method ,(car around)