diff options
| author | Stefan Monnier | 2022-01-31 11:07:06 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2022-01-31 11:07:26 -0500 |
| commit | 1d1b664fbb9232aa40d8daa54a689cfd63d38aa9 (patch) | |
| tree | 164ad10242c8566c3c8fa1d0c12c50804f82d791 /src/data.c | |
| parent | 90bbf27f02b1e7bf9cc0f0206313795c210c565b (diff) | |
| download | emacs-1d1b664fbb9232aa40d8daa54a689cfd63d38aa9.tar.gz emacs-1d1b664fbb9232aa40d8daa54a689cfd63d38aa9.zip | |
(function-history): New symbol property (bug#53632)
Rework the code we have in Fdefalias that tries to keep track
of definitions so as to be able to undo them later.
We used to store in `load-history` when an autoload is redefined as
a non-autoload and in the `autoload` symbol property we used to store
the autoload data that used to be used before it got overriden.
Instead, store the history of the function definition of
a symbol in its `function-history` symbol property.
To make this list cheap in the default case, the latest value is not stored
in the list (since it's in the `symbol-function`) and neither is the first
file. So if there's only been a single definition (the most common case),
the list is empty and the property is just not present at all.
The patch also gets rid of the `autoload` vs `defun` distinction in
`load-history` which seems unnecessary (a significant part of the
motivation for this patch was to get rid of the special handling of
autoloads in this part of the code).
* src/data.c (add_to_function_history): New function.
(defalias): Use it. Don't add the `t` entries for autoloads and always
use `defun` regardless of the kind of definition.
Change `Vautoload_queue` to only hold the function
symbols since the rest is now available from `function-history`.
* src/eval.c (un_autoload): Adjust accordingly.
* src/lread.c (load-history): Udate docstring.
* lisp/loadhist.el (loadhist-unload-filename): New var.
(unload-feature): Bind it.
(loadhist-unload-element): Document its availability.
(loadhist--restore-autoload): Delete var.
(loadhist--unload-function): Delete function.
(loadhist-unload-element): Delete the `t` and `autoload` methods.
Rewrite the `defun` method using `function-history`.
* lisp/help-fns.el: Require `seq`.
(help-fns--autoloaded-p): Rewrite.
(help-fns-function-description-header): Adjust call accordingly.
* doc/lispref/loading.texi (Where Defined): Remove `autoload` and `t`
entries from `load-history` since we don't generate them any more.
Document the `function-history` which replaces the `autoload` property.
(Unloading): Adjust symbol property name accordingly.
* test/lisp/loadhist-resources/loadhist--bar.el:
* test/lisp/loadhist-resources/loadhist--foo.el: New files.
* test/lisp/loadhist-tests.el (loadhist-tests-unload-feature-nested)
(loadhist-tests-unload-feature-notnested): New tests.
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/src/data.c b/src/data.c index a5a76a27554..95d29ac9e98 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -859,6 +859,43 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0, | |||
| 859 | return definition; | 859 | return definition; |
| 860 | } | 860 | } |
| 861 | 861 | ||
| 862 | static void | ||
| 863 | add_to_function_history (Lisp_Object symbol, Lisp_Object olddef) | ||
| 864 | { | ||
| 865 | eassert (!NILP (olddef)); | ||
| 866 | |||
| 867 | Lisp_Object past = Fget (symbol, Qfunction_history); | ||
| 868 | Lisp_Object file = Qnil; | ||
| 869 | /* FIXME: Sadly, `Vload_file_name` gives less precise information | ||
| 870 | (it's sometimes non-nil when it shoujld be nil). */ | ||
| 871 | Lisp_Object tail = Vcurrent_load_list; | ||
| 872 | FOR_EACH_TAIL_SAFE (tail) | ||
| 873 | if (NILP (XCDR (tail)) && STRINGP (XCAR (tail))) | ||
| 874 | file = XCAR (tail); | ||
| 875 | |||
| 876 | Lisp_Object tem = Fplist_member (past, file); | ||
| 877 | if (!NILP (tem)) | ||
| 878 | { /* New def from a file used before. | ||
| 879 | Overwrite the previous record associated with this file. */ | ||
| 880 | if (EQ (tem, past)) | ||
| 881 | /* The new def is from the same file as the last change, so | ||
| 882 | there's nothing to do: unloading the file should revert to | ||
| 883 | the status before the last change rather than before this load. */ | ||
| 884 | return; | ||
| 885 | Lisp_Object pastlen = Flength (past); | ||
| 886 | Lisp_Object temlen = Flength (tem); | ||
| 887 | EMACS_INT tempos = XFIXNUM (pastlen) - XFIXNUM (temlen); | ||
| 888 | eassert (tempos > 1); | ||
| 889 | Lisp_Object prev = Fnthcdr (make_fixnum (tempos - 2), past); | ||
| 890 | /* Remove the previous info for this file. | ||
| 891 | E.g. change `hist` from (... OTHERFILE DEF3 THISFILE DEF2 ...) | ||
| 892 | to (... OTHERFILE DEF2). */ | ||
| 893 | XSETCDR (prev, XCDR (tem)); | ||
| 894 | } | ||
| 895 | /* Push new def from new file. */ | ||
| 896 | Fput (symbol, Qfunction_history, Fcons (file, Fcons (olddef, past))); | ||
| 897 | } | ||
| 898 | |||
| 862 | void | 899 | void |
| 863 | defalias (Lisp_Object symbol, Lisp_Object definition) | 900 | defalias (Lisp_Object symbol, Lisp_Object definition) |
| 864 | { | 901 | { |
| @@ -866,19 +903,19 @@ defalias (Lisp_Object symbol, Lisp_Object definition) | |||
| 866 | bool autoload = AUTOLOADP (definition); | 903 | bool autoload = AUTOLOADP (definition); |
| 867 | if (!will_dump_p () || !autoload) | 904 | if (!will_dump_p () || !autoload) |
| 868 | { /* Only add autoload entries after dumping, because the ones before are | 905 | { /* Only add autoload entries after dumping, because the ones before are |
| 869 | not useful and else we get loads of them from the loaddefs.el. */ | 906 | not useful and else we get loads of them from the loaddefs.el. |
| 870 | Lisp_Object function = XSYMBOL (symbol)->u.s.function; | 907 | That saves us about 110KB in the pdmp file (Jan 2022). */ |
| 871 | 908 | LOADHIST_ATTACH (Fcons (Qdefun, symbol)); | |
| 872 | if (AUTOLOADP (function)) | 909 | } |
| 873 | /* Remember that the function was already an autoload. */ | 910 | } |
| 874 | LOADHIST_ATTACH (Fcons (Qt, symbol)); | ||
| 875 | LOADHIST_ATTACH (Fcons (autoload ? Qautoload : Qdefun, symbol)); | ||
| 876 | |||
| 877 | if (!NILP (Vautoload_queue) && !NILP (function)) | ||
| 878 | Vautoload_queue = Fcons (Fcons (symbol, function), Vautoload_queue); | ||
| 879 | 911 | ||
| 880 | if (AUTOLOADP (function)) | 912 | { |
| 881 | Fput (symbol, Qautoload, XCDR (function)); | 913 | Lisp_Object olddef = XSYMBOL (symbol)->u.s.function; |
| 914 | if (!NILP (olddef)) | ||
| 915 | { | ||
| 916 | if (!NILP (Vautoload_queue)) | ||
| 917 | Vautoload_queue = Fcons (symbol, Vautoload_queue); | ||
| 918 | add_to_function_history (symbol, olddef); | ||
| 882 | } | 919 | } |
| 883 | } | 920 | } |
| 884 | 921 | ||
| @@ -4171,6 +4208,7 @@ syms_of_data (void) | |||
| 4171 | 4208 | ||
| 4172 | DEFSYM (Qinteractive_form, "interactive-form"); | 4209 | DEFSYM (Qinteractive_form, "interactive-form"); |
| 4173 | DEFSYM (Qdefalias_fset_function, "defalias-fset-function"); | 4210 | DEFSYM (Qdefalias_fset_function, "defalias-fset-function"); |
| 4211 | DEFSYM (Qfunction_history, "function-history"); | ||
| 4174 | 4212 | ||
| 4175 | DEFSYM (Qbyte_code_function_p, "byte-code-function-p"); | 4213 | DEFSYM (Qbyte_code_function_p, "byte-code-function-p"); |
| 4176 | 4214 | ||