1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-24 06:20:43 -08:00

(cl--generic-compiler): Revert last change

That change (introduced to circumvent an error now that `seq.el` is
preloaded) caused all dispatchers to be left uncompiled, which slows down
method dispatch very significantly.  Fix the problem in the old way,
i.e. by adding an explicit call to `cl--generic-prefill-dispatchers`.

* lisp/emacs-lisp/cl-generic.el (cl--generic-compiler): Revert last change.
Add (cl--generic-prefill-dispatchers 1 integer) instead to handle
the new dispatchers needed for `seq.el`.
(cl--generic-prefill-generalizer-sample): New function.
(cl--generic-get-dispatcher): Use it to signal an error giving precise
instructions for what to do if we're about the load the byte-compiler
during the preload.
(cl--generic-oclosure-generalizer): Rename from
`cl-generic--oclosure-generalizer` for consistency with all
other generalizers.
This commit is contained in:
Stefan Monnier 2022-06-29 08:58:13 -04:00
parent f70e852ea6
commit 7a9353d444

View file

@ -658,9 +658,13 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
;; 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)
@ -668,6 +672,22 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
;; 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))
@ -932,6 +952,20 @@ those methods.")
(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,
@ -1329,6 +1363,7 @@ See the full list and their hierarchy in `cl--typeof-types'."
(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.
@ -1377,7 +1412,7 @@ Used internally for the (major-mode MODE) context specializers."
(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
@ -1394,7 +1429,7 @@ Used internally for the (major-mode MODE) context specializers."
;; 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)