From b3377e67a7b20a9a53aa2129b2c3951be67ad102 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sat, 1 Jan 2022 22:39:17 +0100 Subject: [PATCH] Remove nil check in exec_byte_code Since we pass no arguments to a non-lexbind bytecode function, we can specify its arity as 0 instead of nil and save a test and branch. * src/bytecode.c (Fbyte_code, exec_byte_code): * src/eval.c (fetch_and_exec_byte_code, funcall_lambda): * src/lisp.h: Change the args_template parameter type to ptrdiff_t, since it is now always a small integer, in exec_byte_code and fetch_and_exec_byte_code, all callers adjusted. --- src/bytecode.c | 54 ++++++++++++++++++++++++-------------------------- src/eval.c | 10 ++++++---- src/lisp.h | 2 +- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/bytecode.c b/src/bytecode.c index 7a9966e20ef..8e0f3d3e4b2 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -333,7 +333,7 @@ If the third argument is incorrect, Emacs may crash. */) } pin_string (bytestr); // Bytecode must be immovable. - return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL); + return exec_byte_code (bytestr, vector, maxdepth, 0, 0, NULL); } static void @@ -344,15 +344,14 @@ bcall0 (Lisp_Object f) /* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect, - emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp - argument list (including &rest, &optional, etc.), and ARGS, of size - NARGS, should be a vector of the actual arguments. The arguments in - ARGS are pushed on the stack according to ARGS_TEMPLATE before - executing BYTESTR. */ + emacs may crash!). ARGS_TEMPLATE is the function arity encoded as an + integer, and ARGS, of size NARGS, should be a vector of the actual + arguments. The arguments in ARGS are pushed on the stack according + to ARGS_TEMPLATE before executing BYTESTR. */ Lisp_Object exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, - Lisp_Object args_template, ptrdiff_t nargs, Lisp_Object *args) + ptrdiff_t args_template, ptrdiff_t nargs, Lisp_Object *args) { #ifdef BYTE_CODE_METER int volatile this_op = 0; @@ -384,26 +383,25 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, unsigned char const *pc = bytestr_data; ptrdiff_t count = SPECPDL_INDEX (); - if (!NILP (args_template)) - { - eassert (FIXNUMP (args_template)); - ptrdiff_t at = XFIXNUM (args_template); - bool rest = (at & 128) != 0; - int mandatory = at & 127; - ptrdiff_t nonrest = at >> 8; - if (! (mandatory <= nargs && (rest || nargs <= nonrest))) - Fsignal (Qwrong_number_of_arguments, - list2 (Fcons (make_fixnum (mandatory), make_fixnum (nonrest)), - make_fixnum (nargs))); - ptrdiff_t pushedargs = min (nonrest, nargs); - for (ptrdiff_t i = 0; i < pushedargs; i++, args++) - PUSH (*args); - if (nonrest < nargs) - PUSH (Flist (nargs - nonrest, args)); - else - for (ptrdiff_t i = nargs - rest; i < nonrest; i++) - PUSH (Qnil); - } + /* ARGS_TEMPLATE is composed of bit fields: + bits 0..6 minimum number of arguments + bits 7 1 iff &rest argument present + bits 8..14 maximum number of arguments */ + bool rest = (args_template & 128) != 0; + int mandatory = args_template & 127; + ptrdiff_t nonrest = args_template >> 8; + if (! (mandatory <= nargs && (rest || nargs <= nonrest))) + Fsignal (Qwrong_number_of_arguments, + list2 (Fcons (make_fixnum (mandatory), make_fixnum (nonrest)), + make_fixnum (nargs))); + ptrdiff_t pushedargs = min (nonrest, nargs); + for (ptrdiff_t i = 0; i < pushedargs; i++, args++) + PUSH (*args); + if (nonrest < nargs) + PUSH (Flist (nargs - nonrest, args)); + else + for (ptrdiff_t i = nargs - rest; i < nonrest; i++) + PUSH (Qnil); while (true) { @@ -671,7 +669,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, val = exec_byte_code (bytecode, AREF (fun, COMPILED_CONSTANTS), AREF (fun, COMPILED_STACK_DEPTH), - template, numargs, args); + XFIXNUM (template), numargs, args); else if (SUBRP (fun) && !SUBR_NATIVE_COMPILED_DYNP (fun)) val = funcall_subr (XSUBR (fun), numargs, args); else diff --git a/src/eval.c b/src/eval.c index 8912e285252..910777e23d5 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3222,15 +3222,16 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args) bytecode string and constants vector, fetch them from the file first. */ static Lisp_Object -fetch_and_exec_byte_code (Lisp_Object fun, Lisp_Object syms_left, +fetch_and_exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, ptrdiff_t nargs, Lisp_Object *args) { if (CONSP (AREF (fun, COMPILED_BYTECODE))) Ffetch_bytecode (fun); + return exec_byte_code (AREF (fun, COMPILED_BYTECODE), AREF (fun, COMPILED_CONSTANTS), AREF (fun, COMPILED_STACK_DEPTH), - syms_left, nargs, args); + args_template, nargs, args); } static Lisp_Object @@ -3308,7 +3309,8 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, argument-binding code below instead (as do all interpreted functions, even lexically bound ones). */ { - return fetch_and_exec_byte_code (fun, syms_left, nargs, arg_vector); + return fetch_and_exec_byte_code (fun, XFIXNUM (syms_left), + nargs, arg_vector); } lexenv = Qnil; } @@ -3394,7 +3396,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, val = XSUBR (fun)->function.a0 (); } else - val = fetch_and_exec_byte_code (fun, Qnil, 0, NULL); + val = fetch_and_exec_byte_code (fun, 0, 0, NULL); return unbind_to (count, val); } diff --git a/src/lisp.h b/src/lisp.h index fdcb7f39d59..54e8c30ccf1 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4700,7 +4700,7 @@ extern int read_bytecode_char (bool); /* Defined in bytecode.c. */ extern void syms_of_bytecode (void); extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object, - Lisp_Object, ptrdiff_t, Lisp_Object *); + ptrdiff_t, ptrdiff_t, Lisp_Object *); extern Lisp_Object get_byte_code_arity (Lisp_Object); /* Defined in macros.c. */ -- 2.39.2