(defun make-final-checking-dfun (generic-function function
classes-list new-class)
- (let ((metatypes (arg-info-metatypes (gf-arg-info generic-function))))
+ (multiple-value-bind (nreq applyp metatypes nkeys)
+ (get-generic-fun-info generic-function)
+ (declare (ignore nreq applyp nkeys))
(if (every (lambda (mt) (eq mt t)) metatypes)
(values (lambda (&rest args)
(invoke-emf function args))
(some (lambda (method)
(let ((fmf (if (listp method)
(third method)
- (method-fast-function method))))
+ (safe-method-fast-function method))))
(method-function-get fmf :slot-name-lists)))
;; KLUDGE: As of sbcl-0.6.4, it's very important for
;; efficiency to know the type of the sequence argument to
(dolist (method methods t)
(when (eq *boot-state* 'complete)
(when (or (some #'eql-specializer-p
- (method-specializers method))
- (method-qualifiers method))
+ (safe-method-specializers method))
+ (safe-method-qualifiers method))
(return nil)))
(let ((value (method-function-get
(if early-p
(or (third method) (second method))
- (or (method-fast-function method)
- (method-function method)))
+ (or (safe-method-fast-function method)
+ (safe-method-function method)))
:constant-value default)))
(when (or (eq value default)
(and boolean-values-p
(defun use-dispatch-dfun-p (gf &optional (caching-p (use-caching-dfun-p gf)))
(when (eq *boot-state* 'complete)
- (unless (or caching-p (gf-requires-emf-keyword-checks gf))
+ (unless (or caching-p
+ (gf-requires-emf-keyword-checks gf))
;; This should return T when almost all dispatching is by
;; eql specializers or built-in classes. In other words,
;; return NIL if we might ever need to do more than
(defparameter *secondary-dfun-call-cost* 1)
(defun caching-dfun-cost (gf)
- (let* ((arg-info (gf-arg-info gf))
- (nreq (length (arg-info-metatypes arg-info))))
+ (let ((nreq (get-generic-fun-info gf)))
(+ *cache-lookup-cost*
(* *wrapper-of-cost* nreq)
(if (methods-contain-eql-specializer-p
(defun make-initial-dfun (gf)
(let ((initial-dfun
- #'(instance-lambda (&rest args)
+ #'(lambda (&rest args)
(initial-dfun gf args))))
(multiple-value-bind (dfun cache info)
(cond
(let* ((methods (early-gf-methods gf))
(slot-name (early-method-standard-accessor-slot-name (car methods))))
(ecase type
- (reader #'(instance-lambda (instance)
+ (reader #'(lambda (instance)
(let* ((class (class-of instance))
(class-name (!bootstrap-get-slot 'class class 'name)))
(!bootstrap-get-slot class-name instance slot-name))))
- (boundp #'(instance-lambda (instance)
+ (boundp #'(lambda (instance)
(let* ((class (class-of instance))
(class-name (!bootstrap-get-slot 'class class 'name)))
(not (eq +slot-unbound+
(!bootstrap-get-slot class-name
instance slot-name))))))
- (writer #'(instance-lambda (new-value instance)
+ (writer #'(lambda (new-value instance)
(let* ((class (class-of instance))
(class-name (!bootstrap-get-slot 'class class 'name)))
(!bootstrap-set-slot class-name instance slot-name new-value)))))))
specls all-same-p)
(cond ((null methods)
(values
- #'(instance-lambda (&rest args)
+ #'(lambda (&rest args)
(apply #'no-applicable-method gf args))
nil
(no-methods-dfun-info)))
(t
(make-final-caching-dfun gf classes-list new-class)))))
+(defvar *accessor-miss-history* nil)
+
(defun accessor-miss (gf new object dfun-info)
- (let* ((ostate (type-of dfun-info))
- (otype (dfun-info-accessor-type dfun-info))
- oindex ow0 ow1 cache
- (args (ecase otype
- ;; The congruence rules ensure that this is safe
- ;; despite not knowing the new type yet.
- ((reader boundp) (list object))
- (writer (list new object)))))
- (dfun-miss (gf args wrappers invalidp nemf ntype nindex)
-
- ;; The following lexical functions change the state of the
- ;; dfun to that which is their name. They accept arguments
- ;; which are the parameters of the new state, and get other
- ;; information from the lexical variables bound above.
- (flet ((two-class (index w0 w1)
+ (let ((wrapper (wrapper-of object))
+ (previous-miss (assq gf *accessor-miss-history*)))
+ (when (eq wrapper (cdr previous-miss))
+ (error "~@<Vicious metacircle: The computation of a ~
+ dfun of ~s for argument ~s uses the dfun being ~
+ computed.~@:>"
+ gf object))
+ (let* ((*accessor-miss-history* (acons gf wrapper *accessor-miss-history*))
+ (ostate (type-of dfun-info))
+ (otype (dfun-info-accessor-type dfun-info))
+ oindex ow0 ow1 cache
+ (args (ecase otype
+ ((reader boundp) (list object))
+ (writer (list new object)))))
+ (dfun-miss (gf args wrappers invalidp nemf ntype nindex)
+ ;; The following lexical functions change the state of the
+ ;; dfun to that which is their name. They accept arguments
+ ;; which are the parameters of the new state, and get other
+ ;; information from the lexical variables bound above.
+ (flet ((two-class (index w0 w1)
(when (zerop (random 2)) (psetf w0 w1 w1 w0))
(dfun-update gf
#'make-two-class-accessor-dfun
(setq cache (dfun-info-cache dfun-info))
(if (consp nindex)
(caching)
- (do-fill #'n-n))))))))))
+ (do-fill #'n-n)))))))))))
(defun checking-miss (generic-function args dfun-info)
(let ((oemf (dfun-info-function dfun-info))
(if (consp meth)
(and (early-method-standard-accessor-p meth)
(early-method-standard-accessor-slot-name meth))
- (and (member *the-class-std-object*
+ (and (member *the-class-standard-object*
(if early-p
(early-class-precedence-list
accessor-class)
(early-class-precedence-list specl)
(and (class-finalized-p specl)
(class-precedence-list specl))))
- (so-p (member *the-class-std-object* specl-cpl))
+ (so-p (member *the-class-standard-object* specl-cpl))
(slot-name (if (consp method)
(and (early-method-standard-accessor-p method)
(early-method-standard-accessor-slot-name
(class-precedence-list class))))
(when (memq specl cpl)
(unless (and (or so-p
- (member *the-class-std-object* cpl))
+ (member *the-class-standard-object*
+ cpl))
(or early-p
(slot-accessor-std-p slotd type)))
(return-from make-accessor-table nil))
(let ((definite-p t) (possibly-applicable-methods nil))
(dolist (method (if (early-gf-p generic-function)
(early-gf-methods generic-function)
- (generic-function-methods generic-function)))
+ (safe-generic-function-methods generic-function)))
(let ((specls (if (consp method)
(early-method-specializers method t)
- (method-specializers method)))
+ (safe-method-specializers method)))
(types types)
(possibly-applicable-p t) (applicable-p t))
(dolist (specl specls)
(when possibly-applicable-p
(unless applicable-p (setq definite-p nil))
(push method possibly-applicable-methods))))
- (let ((precedence (arg-info-precedence (if (early-gf-p generic-function)
- (early-gf-arg-info
- generic-function)
- (gf-arg-info
- generic-function)))))
- (values (sort-applicable-methods precedence
- (nreverse possibly-applicable-methods)
- types)
- definite-p))))
+ (multiple-value-bind (nreq applyp metatypes nkeys arg-info)
+ (get-generic-fun-info generic-function)
+ (declare (ignore nreq applyp metatypes nkeys))
+ (let* ((precedence (arg-info-precedence arg-info)))
+ (values (sort-applicable-methods precedence
+ (nreverse possibly-applicable-methods)
+ types)
+ definite-p)))))
(defun sort-applicable-methods (precedence methods types)
(sort-methods methods
'specializer-applicable-using-type-p
type)))))
-(defun map-all-classes (function &optional (root t))
- (let ((braid-p (or (eq *boot-state* 'braid)
+(defun map-all-classes (fun &optional (root t))
+ (let ((all-classes (make-hash-table :test 'eq))
+ (braid-p (or (eq *boot-state* 'braid)
(eq *boot-state* 'complete))))
(labels ((do-class (class)
- (mapc #'do-class
- (if braid-p
- (class-direct-subclasses class)
- (early-class-direct-subclasses class)))
- (funcall function class)))
+ (unless (gethash class all-classes)
+ (setf (gethash class all-classes) t)
+ (funcall fun class)
+ (mapc #'do-class
+ (if braid-p
+ (class-direct-subclasses class)
+ (early-class-direct-subclasses class))))))
(do-class (if (symbolp root)
(find-class root)
root)))))
(if function-p
(lambda (method-alist wrappers)
(declare (ignore method-alist wrappers))
- #'(instance-lambda (&rest args)
+ #'(lambda (&rest args)
(apply #'no-applicable-method gf args)))
(lambda (method-alist wrappers)
(declare (ignore method-alist wrappers))
(return t)))))
\f
(defun update-dfun (generic-function &optional dfun cache info)
- (let* ((early-p (early-gf-p generic-function))
- (gf-name (if early-p
- (!early-gf-name generic-function)
- (generic-function-name generic-function))))
+ (let* ((early-p (early-gf-p generic-function)))
(set-dfun generic-function dfun cache info)
(let ((dfun (if early-p
(or dfun (make-initial-dfun generic-function))
(compute-discriminating-function generic-function))))
(set-funcallable-instance-function generic-function dfun)
- (set-fun-name generic-function gf-name)
- dfun)))
+ (let ((gf-name (if early-p
+ (!early-gf-name generic-function)
+ (generic-function-name generic-function))))
+ (set-fun-name generic-function gf-name)
+ dfun))))
\f
(defvar *dfun-count* nil)
(defvar *dfun-list* nil)