From f0b0105d913a94c66f230874c9269b19dbbc83bd Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 19 May 2020 23:22:40 -0700 Subject: Hoist some byte-code checking out of eval Check Lisp_Compiled objects better as they’re created, so that the byte-code interpreter needn’t do the checks each time it executes them. This improved performance of ‘make compile-always’ by 1.5% on my platform. Also, improve the quality of the (still-incomplete) checks, as this is more practical now that they’re done less often. * src/alloc.c (make_byte_code): Remove. All uses removed. (Fmake_byte_code): Put a better (though still incomplete) check here instead. Simplify by using Fvector instead of make_uninit_vector followed by memcpy, and by using XSETPVECTYPE instead of make_byte_code followed by XSETCOMPILED. * src/bytecode.c (Fbyte_code): Do sanity check and conditional translation to unibyte here instead of each time the function is executed. (exec_byte_code): Omit no-longer-necessary sanity and unibyte checking. Use SCHARS instead of SBYTES where either will do, as SCHARS is faster. * src/eval.c (fetch_and_exec_byte_code): New function. (funcall_lambda): Use it. (funcall_lambda, lambda_arity, Ffetch_bytecode): Omit no-longer-necessary sanity checks. (Ffetch_bytecode): Add sanity check if actually fetching. * src/lisp.h (XSETCOMPILED): Remove. All uses removed. * src/lread.c (read1): Check byte-code objects more thoroughly, albeit still incompletely, and do translation to unibyte here instead of each time the function is executed. (read1): Use XSETPVECYPE instead of make_byte_code. (read_vector): Omit no-longer-necessary sanity check. --- src/alloc.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index ebc55857ea0..b7ebaa63a5b 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3421,23 +3421,6 @@ usage: (vector &rest OBJECTS) */) return val; } -void -make_byte_code (struct Lisp_Vector *v) -{ - /* Don't allow the global zero_vector to become a byte code object. */ - eassert (0 < v->header.size); - - if (v->header.size > 1 && STRINGP (v->contents[1]) - && STRING_MULTIBYTE (v->contents[1])) - /* BYTECODE-STRING must have been produced by Emacs 20.2 or the - earlier because they produced a raw 8-bit string for byte-code - and now such a byte-code string is loaded as multibyte while - raw 8-bit characters converted to multibyte form. Thus, now we - must convert them back to the original unibyte form. */ - v->contents[1] = Fstring_as_unibyte (v->contents[1]); - XSETPVECTYPE (v, PVEC_COMPILED); -} - DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0, doc: /* Create a byte-code object with specified arguments as elements. The arguments should be the ARGLIST, bytecode-string BYTE-CODE, constant @@ -3456,8 +3439,14 @@ stack before executing the byte-code. usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - Lisp_Object val = make_uninit_vector (nargs); - struct Lisp_Vector *p = XVECTOR (val); + if (! ((FIXNUMP (args[COMPILED_ARGLIST]) + || CONSP (args[COMPILED_ARGLIST]) + || NILP (args[COMPILED_ARGLIST])) + && STRINGP (args[COMPILED_BYTECODE]) + && !STRING_MULTIBYTE (args[COMPILED_BYTECODE]) + && VECTORP (args[COMPILED_CONSTANTS]) + && FIXNATP (args[COMPILED_STACK_DEPTH]))) + error ("Invalid byte-code object"); /* We used to purecopy everything here, if purify-flag was set. This worked OK for Emacs-23, but with Emacs-24's lexical binding code, it can be @@ -3466,10 +3455,8 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT copied into pure space, including its free variables, which is sometimes just wasteful and other times plainly wrong (e.g. those free vars may want to be setcar'd). */ - - memcpy (p->contents, args, nargs * sizeof *args); - make_byte_code (p); - XSETCOMPILED (val, p); + Lisp_Object val = Fvector (nargs, args); + XSETPVECTYPE (XVECTOR (val), PVEC_COMPILED); return val; } -- cgit v1.2.1 From 6b3fb29ede140c79a4146fb2056306632e3bd511 Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Tue, 19 May 2020 22:33:38 +0100 Subject: ; src/alloc.c: Add a GC reg spill mechanism and Bug#41357 related commentary. --- src/alloc.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index b7ebaa63a5b..d5a6d9167ea 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -4998,8 +4998,9 @@ mark_stack (char const *bottom, char const *end) #endif } -/* This is a trampoline function that flushes registers to the stack, - and then calls FUNC. ARG is passed through to FUNC verbatim. +/* flush_stack_call_func is the trampoline function that flushes + registers to the stack, and then calls FUNC. ARG is passed through + to FUNC verbatim. This function must be called whenever Emacs is about to release the global interpreter lock. This lets the garbage collector easily @@ -5007,7 +5008,20 @@ mark_stack (char const *bottom, char const *end) Lisp. It is invalid to run any Lisp code or to allocate any GC memory - from FUNC. */ + from FUNC. + + Note: all register spilling is done in flush_stack_call_func before + flush_stack_call_func1 is activated. + + flush_stack_call_func1 is responsible for identifying the stack + address range to be scanned. It *must* be carefully kept as + noinline to make sure that registers has been spilled before it is + called, otherwise given __builtin_frame_address (0) typically + returns the frame pointer (base pointer) and not the stack pointer + [1] GC will miss to scan callee-saved registers content + (Bug#41357). + + [1] . */ NO_INLINE void flush_stack_call_func1 (void (*func) (void *arg), void *arg) -- cgit v1.2.1