;; compiled. Otherwise the byte-compiler and all the code on
;; which it depends needs to be usable before cl-generic is loaded,
;; which imposes a significant burden on the bootstrap.
- (if (or (consp (lambda (x) (+ x 1)))
- (not (featurep 'bytecomp)))
+ (if (consp (lambda (x) (+ x 1)))
(lambda (exp) (eval exp t))
+ ;; But do byte-compile the dispatchers once bootstrap is passed:
+ ;; the performance difference is substantial (like a 5x speedup on
+ ;; the `eieio' elisp-benchmark)).
+ ;; To avoid loading the byte-compiler during the final preload,
+ ;; see `cl--generic-prefill-dispatchers'.
#'byte-compile))
(defun cl--generic-get-dispatcher (dispatch)
;; We need `copy-sequence` here because this `dispatch' object might be
;; modified by side-effect in `cl-generic-define-method' (bug#46722).
(gethash (copy-sequence dispatch) cl--generic-dispatchers)
+
+ (when (and purify-flag ;FIXME: Is this a reliable test of the final dump?
+ (eq cl--generic-compiler #'byte-compile))
+ ;; We don't want to preload the byte-compiler!!
+ (error
+ "Missing cl-generic dispatcher in the prefilled cache!
+Missing for: %S
+You might need to add: %S"
+ (mapcar (lambda (x) (if (cl--generic-generalizer-p x)
+ (cl--generic-generalizer-name x)
+ x))
+ dispatch)
+ `(cl--generic-prefill-dispatchers
+ ,@(delq nil (mapcar #'cl--generic-prefill-generalizer-sample
+ dispatch)))))
+
;; (message "cl--generic-get-dispatcher (%S)" dispatch)
(let* ((dispatch-arg (car dispatch))
(generalizers (cdr dispatch))
(if (eq specializer t) (list cl--generic-t-generalizer)
(error "Unknown specializer %S" specializer)))
+(defun cl--generic-prefill-generalizer-sample (x)
+ "Return an example specializer."
+ (if (not (cl--generic-generalizer-p x))
+ x
+ (pcase (cl--generic-generalizer-name x)
+ ('cl--generic-t-generalizer nil)
+ ('cl--generic-head-generalizer '(head 'x))
+ ('cl--generic-eql-generalizer '(eql 'x))
+ ('cl--generic-struct-generalizer 'cl--generic)
+ ('cl--generic-typeof-generalizer 'integer)
+ ('cl--generic-derived-generalizer '(derived-mode c-mode))
+ ('cl--generic-oclosure-generalizer 'oclosure)
+ (_ x))))
+
(eval-when-compile
;; This macro is brittle and only really important in order to be
;; able to preload cl-generic without also preloading the byte-compiler,
(cl-call-next-method)))
(cl--generic-prefill-dispatchers 0 integer)
+(cl--generic-prefill-dispatchers 1 integer)
(cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer)
;;; Dispatch on major mode.
(when (cl-typep class 'oclosure--class)
(oclosure--class-allparents class)))))
-(cl-generic-define-generalizer cl-generic--oclosure-generalizer
+(cl-generic-define-generalizer cl--generic-oclosure-generalizer
;; Give slightly higher priority than the struct specializer, so that
;; for a generic function with methods dispatching structs and on OClosures,
;; we first try `oclosure-type' before `type-of' since `type-of' will return
;; take place without requiring cl-lib.
(let ((class (cl--find-class type)))
(and (cl-typep class 'oclosure--class)
- (list cl-generic--oclosure-generalizer))))
+ (list cl--generic-oclosure-generalizer))))
(cl-call-next-method)))
(cl--generic-prefill-dispatchers 0 oclosure)