diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2021-02-21 15:24:41 +0100 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2021-02-21 21:58:25 +0100 |
commit | d0c47652e527397cae96444c881bf60455c763c1 (patch) | |
tree | 9dfa3ce23f5251726ebd287298486667a135101b /lisp/emacs-lisp/bytecomp.el | |
parent | 2790c6a572a905359c60f055c682b28ef5c8ff0d (diff) | |
download | emacs-d0c47652e527397cae96444c881bf60455c763c1.tar.gz emacs-d0c47652e527397cae96444c881bf60455c763c1.tar.bz2 emacs-d0c47652e527397cae96444c881bf60455c763c1.zip |
Faster, more compact, and readable closure creation
Simplify closure creation by calling a single function at run time
instead of putting it together from small pieces. This is faster
(by about a factor 2), takes less space on disk and in memory, and
makes internal functions somewhat readable in disassembly listings again.
This is done by creating a prototype function at compile-time whose
closure variables are placeholder values V0, V1... which can be seen
in the disassembly. The prototype is then cloned at run time using
the new make-closure function that replaces the placeholders with
the actual closure variables.
* lisp/emacs-lisp/bytecomp.el (byte-compile-make-closure):
Generate call to make-closure from a prototype function.
* src/alloc.c (Fmake_closure): New function.
(syms_of_alloc): Defsubr it.
* src/data.c (syms_of_data): Defsym byte-code-function-p.
Diffstat (limited to 'lisp/emacs-lisp/bytecomp.el')
-rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 1b0906b50bb..69a63b169cc 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -3817,15 +3817,21 @@ discarding." (cl-assert (or (> (length env) 0) docstring-exp)) ;Otherwise, we don't need a closure. (cl-assert (byte-code-function-p fun)) - (byte-compile-form `(make-byte-code - ',(aref fun 0) ',(aref fun 1) - (vconcat (vector . ,env) ',(aref fun 2)) - ,@(let ((rest (nthcdr 3 (mapcar (lambda (x) `',x) fun)))) - (if docstring-exp - `(,(car rest) - ,docstring-exp - ,@(cddr rest)) - rest))))))) + (byte-compile-form + ;; Use symbols V0, V1 ... as placeholders for closure variables: + ;; they should be short (to save space in the .elc file), yet + ;; distinct when disassembled. + (let* ((dummy-vars (mapcar (lambda (i) (intern (format "V%d" i))) + (number-sequence 0 (1- (length env))))) + (proto-fun + (apply #'make-byte-code + (aref fun 0) (aref fun 1) + ;; Prepend dummy cells to the constant vector, + ;; to get the indices right when disassembling. + (vconcat dummy-vars (aref fun 2)) + (mapcar (lambda (i) (aref fun i)) + (number-sequence 3 (1- (length fun))))))) + `(make-closure ,proto-fun ,@env)))))) (defun byte-compile-get-closed-var (form) "Byte-compile the special `internal-get-closed-var' form." |