aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorMattias EngdegÄrd2021-02-21 15:24:41 +0100
committerMattias EngdegÄrd2021-02-21 21:58:25 +0100
commitd0c47652e527397cae96444c881bf60455c763c1 (patch)
tree9dfa3ce23f5251726ebd287298486667a135101b /src/alloc.c
parent2790c6a572a905359c60f055c682b28ef5c8ff0d (diff)
downloademacs-d0c47652e527397cae96444c881bf60455c763c1.tar.gz
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 'src/alloc.c')
-rw-r--r--src/alloc.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/alloc.c b/src/alloc.c
index b86ed4ed262..e72fc4c4332 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3498,6 +3498,38 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
3498 return val; 3498 return val;
3499} 3499}
3500 3500
3501DEFUN ("make-closure", Fmake_closure, Smake_closure, 1, MANY, 0,
3502 doc: /* Create a byte-code closure from PROTOTYPE and CLOSURE-VARS.
3503Return a copy of PROTOTYPE, a byte-code object, with CLOSURE-VARS
3504replacing the elements in the beginning of the constant-vector.
3505usage: (make-closure PROTOTYPE &rest CLOSURE-VARS) */)
3506 (ptrdiff_t nargs, Lisp_Object *args)
3507{
3508 Lisp_Object protofun = args[0];
3509 CHECK_TYPE (COMPILEDP (protofun), Qbyte_code_function_p, protofun);
3510
3511 /* Create a copy of the constant vector, filling it with the closure
3512 variables in the beginning. (The overwritten part should just
3513 contain placeholder values.) */
3514 Lisp_Object proto_constvec = AREF (protofun, COMPILED_CONSTANTS);
3515 ptrdiff_t constsize = ASIZE (proto_constvec);
3516 ptrdiff_t nvars = nargs - 1;
3517 if (nvars > constsize)
3518 error ("Closure vars do not fit in constvec");
3519 Lisp_Object constvec = make_uninit_vector (constsize);
3520 memcpy (XVECTOR (constvec)->contents, args + 1, nvars * word_size);
3521 memcpy (XVECTOR (constvec)->contents + nvars,
3522 XVECTOR (proto_constvec)->contents + nvars,
3523 (constsize - nvars) * word_size);
3524
3525 /* Return a copy of the prototype function with the new constant vector. */
3526 ptrdiff_t protosize = PVSIZE (protofun);
3527 struct Lisp_Vector *v = allocate_vectorlike (protosize, false);
3528 v->header = XVECTOR (protofun)->header;
3529 memcpy (v->contents, XVECTOR (protofun)->contents, protosize * word_size);
3530 v->contents[COMPILED_CONSTANTS] = constvec;
3531 return make_lisp_ptr (v, Lisp_Vectorlike);
3532}
3501 3533
3502 3534
3503/*********************************************************************** 3535/***********************************************************************
@@ -7573,6 +7605,7 @@ N should be nonnegative. */);
7573 defsubr (&Srecord); 7605 defsubr (&Srecord);
7574 defsubr (&Sbool_vector); 7606 defsubr (&Sbool_vector);
7575 defsubr (&Smake_byte_code); 7607 defsubr (&Smake_byte_code);
7608 defsubr (&Smake_closure);
7576 defsubr (&Smake_list); 7609 defsubr (&Smake_list);
7577 defsubr (&Smake_vector); 7610 defsubr (&Smake_vector);
7578 defsubr (&Smake_record); 7611 defsubr (&Smake_record);