From b7f83adda5a32140811e8e7decc4394d64cada3d Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 19 Jan 2015 00:56:18 -0800 Subject: [PATCH] Prefer memset to repeatedly assigning Qnil * alloc.c (allocate_pseudovector): Catch more bogus values. * alloc.c (allocate_pseudovector): * callint.c (Fcall_interactively): * coding.c (syms_of_coding): * fringe.c (init_fringe): Verify that Qnil == 0. * callint.c (Fcall_interactively): * eval.c (Fapply, Ffuncall): * fns.c (mapcar1, larger_vector): * font.c (font_expand_wildcards): * fringe.c (init_fringe): Prefer memset to assigning zeros by hand. * callint.c (Fcall_interactively): Remove duplicate assignment of Qnil to args[i]. * coding.c (syms_of_coding): Prefer LISP_INITIALLY_ZERO to assigning zeros by hand. * fileio.c (Ffile_selinux_context): Rewrite to avoid need for Lisp_Object array. * lisp.h (XLI_BUILTIN_LISPSYM): New macro. (DEFINE_LISP_SYMBOL_END): Use it. (NIL_IS_ZERO): New constant. (memsetnil): New function. --- src/ChangeLog | 26 ++++++++++++++++++++++++++ src/alloc.c | 6 ++++-- src/callint.c | 10 +++------- src/coding.c | 9 +++------ src/eval.c | 11 +++++------ src/fileio.c | 17 +++++++---------- src/fns.c | 13 +++++-------- src/font.c | 7 +++---- src/fringe.c | 7 ++----- src/lisp.h | 24 +++++++++++++++++++++--- 10 files changed, 79 insertions(+), 51 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 16e2fa19626..04b952cae60 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,29 @@ +2015-01-19 Paul Eggert + + Prefer memset to repeatedly assigning Qnil + * alloc.c (allocate_pseudovector): Catch more bogus values. + * alloc.c (allocate_pseudovector): + * callint.c (Fcall_interactively): + * coding.c (syms_of_coding): + * fringe.c (init_fringe): + Verify that Qnil == 0. + * callint.c (Fcall_interactively): + * eval.c (Fapply, Ffuncall): + * fns.c (mapcar1, larger_vector): + * font.c (font_expand_wildcards): + * fringe.c (init_fringe): + Prefer memset to assigning zeros by hand. + * callint.c (Fcall_interactively): + Remove duplicate assignment of Qnil to args[i]. + * coding.c (syms_of_coding): + Prefer LISP_INITIALLY_ZERO to assigning zeros by hand. + * fileio.c (Ffile_selinux_context): + Rewrite to avoid need for Lisp_Object array. + * lisp.h (XLI_BUILTIN_LISPSYM): New macro. + (DEFINE_LISP_SYMBOL_END): Use it. + (NIL_IS_ZERO): New constant. + (memsetnil): New function. + 2015-01-16 Dmitry Antipov Tune pseudovector allocation assuming Qnil == 0. diff --git a/src/alloc.c b/src/alloc.c index 22a15b4ac59..2c7b02f1158 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3169,12 +3169,14 @@ allocate_pseudovector (int memlen, int lisplen, struct Lisp_Vector *v = allocate_vectorlike (memlen); /* Catch bogus values. */ - eassert (tag <= PVEC_FONT); + eassert (0 <= tag && tag <= PVEC_FONT); + eassert (0 <= lisplen && lisplen <= zerolen && zerolen <= memlen); eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1); eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1); - /* Only the first lisplen slots will be traced normally by the GC. + /* Only the first LISPLEN slots will be traced normally by the GC. But since Qnil == 0, we can memset Lisp_Object slots as well. */ + verify (NIL_IS_ZERO); memset (v->contents, 0, zerolen * word_size); XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen); diff --git a/src/callint.c b/src/callint.c index dd238b976aa..3a595b57d77 100644 --- a/src/callint.c +++ b/src/callint.c @@ -509,12 +509,8 @@ invoke it. If KEYS is omitted or nil, the return value of visargs = args + nargs; varies = (signed char *) (visargs + nargs); - for (i = 0; i < nargs; i++) - { - args[i] = Qnil; - visargs[i] = Qnil; - varies[i] = 0; - } + verify (NIL_IS_ZERO); + memset (args, 0, nargs * (2 * word_size + 1)); GCPRO5 (prefix_arg, function, *args, *visargs, up_event); gcpro3.nvars = nargs; @@ -781,7 +777,7 @@ invoke it. If KEYS is omitted or nil, the return value of argument if no prefix. */ if (NILP (prefix_arg)) { - args[i] = Qnil; + /* args[i] = Qnil; */ varies[i] = -1; } else diff --git a/src/coding.c b/src/coding.c index b11143a32fb..77cea77cef5 100644 --- a/src/coding.c +++ b/src/coding.c @@ -11272,13 +11272,10 @@ internal character representation. */); Vtranslation_table_for_input = Qnil; { - Lisp_Object args[coding_arg_undecided_max]; - Lisp_Object plist[16]; - int i; - - for (i = 0; i < coding_arg_undecided_max; i++) - args[i] = Qnil; + verify (NIL_IS_ZERO); + Lisp_Object args[coding_arg_undecided_max] = { LISP_INITIALLY_ZERO, }; + Lisp_Object plist[16]; plist[0] = intern_c_string (":name"); plist[1] = args[coding_arg_name] = Qno_conversion; plist[2] = intern_c_string (":mnemonic"); diff --git a/src/eval.c b/src/eval.c index 5cadb1bc2de..ddf6535cabc 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2299,8 +2299,7 @@ usage: (apply FUNCTION &rest ARGUMENTS) */) /* Avoid making funcall cons up a yet another new vector of arguments by explicitly supplying nil's for optional values. */ SAFE_ALLOCA_LISP (funcall_args, 1 + XSUBR (fun)->max_args); - for (i = numargs; i < XSUBR (fun)->max_args; /* nothing */) - funcall_args[++i] = Qnil; + memsetnil (funcall_args + numargs + 1, XSUBR (fun)->max_args - numargs); funcall_nargs = 1 + XSUBR (fun)->max_args; } else @@ -2638,8 +2637,8 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) ptrdiff_t numargs = nargs - 1; Lisp_Object lisp_numargs; Lisp_Object val; - register Lisp_Object *internal_args; - ptrdiff_t i, count; + Lisp_Object *internal_args; + ptrdiff_t count; QUIT; @@ -2694,8 +2693,8 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) eassert (XSUBR (fun)->max_args <= ARRAYELTS (internal_argbuf)); internal_args = internal_argbuf; memcpy (internal_args, args + 1, numargs * word_size); - for (i = numargs; i < XSUBR (fun)->max_args; i++) - internal_args[i] = Qnil; + memsetnil (internal_args + numargs, + XSUBR (fun)->max_args - numargs); } else internal_args = args + 1; diff --git a/src/fileio.c b/src/fileio.c index dc67a00ed2a..ff6720d4ae2 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2812,7 +2812,8 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */) (Lisp_Object filename) { Lisp_Object absname; - Lisp_Object values[4]; + Lisp_Object user = Qnil, role = Qnil, type = Qnil, range = Qnil; + Lisp_Object handler; #if HAVE_LIBSELINUX security_context_t con; @@ -2830,10 +2831,6 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */) absname = ENCODE_FILE (absname); - values[0] = Qnil; - values[1] = Qnil; - values[2] = Qnil; - values[3] = Qnil; #if HAVE_LIBSELINUX if (is_selinux_enabled ()) { @@ -2842,20 +2839,20 @@ or if SELinux is disabled, or if Emacs lacks SELinux support. */) { context = context_new (con); if (context_user_get (context)) - values[0] = build_string (context_user_get (context)); + user = build_string (context_user_get (context)); if (context_role_get (context)) - values[1] = build_string (context_role_get (context)); + role = build_string (context_role_get (context)); if (context_type_get (context)) - values[2] = build_string (context_type_get (context)); + type = build_string (context_type_get (context)); if (context_range_get (context)) - values[3] = build_string (context_range_get (context)); + range = build_string (context_range_get (context)); context_free (context); freecon (con); } } #endif - return Flist (ARRAYELTS (values), values); + return list4 (user, role, type, range); } DEFUN ("set-file-selinux-context", Fset_file_selinux_context, diff --git a/src/fns.c b/src/fns.c index ca3d98b23dd..d177294480a 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2517,16 +2517,14 @@ usage: (nconc &rest LISTS) */) static void mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq) { - register Lisp_Object tail; - Lisp_Object dummy; - register EMACS_INT i; + Lisp_Object tail, dummy; + EMACS_INT i; struct gcpro gcpro1, gcpro2, gcpro3; if (vals) { /* Don't let vals contain any garbage when GC happens. */ - for (i = 0; i < leni; i++) - vals[i] = Qnil; + memsetnil (vals, leni); GCPRO3 (dummy, fn, seq); gcpro1.var = vals; @@ -3688,7 +3686,7 @@ Lisp_Object larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) { struct Lisp_Vector *v; - ptrdiff_t i, incr, incr_max, old_size, new_size; + ptrdiff_t incr, incr_max, old_size, new_size; ptrdiff_t C_language_max = min (PTRDIFF_MAX, SIZE_MAX) / sizeof *v->contents; ptrdiff_t n_max = (0 <= nitems_max && nitems_max < C_language_max ? nitems_max : C_language_max); @@ -3702,8 +3700,7 @@ larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) new_size = old_size + incr; v = allocate_vector (new_size); memcpy (v->contents, XVECTOR (vec)->contents, old_size * sizeof *v->contents); - for (i = old_size; i < new_size; ++i) - v->contents[i] = Qnil; + memsetnil (v->contents + old_size, new_size - old_size); XSETVECTOR (vec, v); return vec; } diff --git a/src/font.c b/src/font.c index 56a27821718..190b33a8ef0 100644 --- a/src/font.c +++ b/src/font.c @@ -989,15 +989,14 @@ font_expand_wildcards (Lisp_Object *field, int n) if (i == 0 || ! NILP (tmp[i - 1])) /* None of TMP[X] corresponds to Jth field. */ return -1; - for (; j < range[i].from; j++) - field[j] = Qnil; + memsetnil (field + j, range[i].from - j); + j = range[i].from; } field[j++] = tmp[i]; } if (! NILP (tmp[n - 1]) && j < XLFD_REGISTRY_INDEX) return -1; - for (; j < XLFD_LAST_INDEX; j++) - field[j] = Qnil; + memsetnil (field + j, XLFD_LAST_INDEX - j); if (INTEGERP (field[XLFD_ENCODING_INDEX])) field[XLFD_ENCODING_INDEX] = Fintern (Fnumber_to_string (field[XLFD_ENCODING_INDEX]), Qnil); diff --git a/src/fringe.c b/src/fringe.c index c7262d19336..464379d0cd0 100644 --- a/src/fringe.c +++ b/src/fringe.c @@ -1723,15 +1723,12 @@ init_fringe_once (void) void init_fringe (void) { - int i; - max_fringe_bitmaps = MAX_STANDARD_FRINGE_BITMAPS + 20; fringe_bitmaps = xzalloc (max_fringe_bitmaps * sizeof *fringe_bitmaps); - fringe_faces = xmalloc (max_fringe_bitmaps * sizeof *fringe_faces); - for (i = 0; i < max_fringe_bitmaps; i++) - fringe_faces[i] = Qnil; + verify (NIL_IS_ZERO); + fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces); } #ifdef HAVE_NTGUI diff --git a/src/lisp.h b/src/lisp.h index 7c7d3f3e2e5..a1ea35574c3 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -732,14 +732,18 @@ struct Lisp_Symbol TAG_PTR (Lisp_Symbol, \ ((uintptr_t) (offset) >> (USE_LSB_TAG ? 0 : GCTYPEBITS))) +/* XLI_BUILTIN_LISPSYM (iQwhatever) is equivalent to + XLI (builtin_lisp_symbol (Qwhatever)), + except the former expands to an integer constant expression. */ +#define XLI_BUILTIN_LISPSYM(iname) TAG_SYMOFFSET ((iname) * sizeof *lispsym) + /* Declare extern constants for Lisp symbols. These can be helpful when using a debugger like GDB, on older platforms where the debug format does not represent C macros. */ #define DEFINE_LISP_SYMBOL_BEGIN(name) \ - DEFINE_GDB_SYMBOL_BEGIN (Lisp_Object, name) + DEFINE_GDB_SYMBOL_BEGIN (Lisp_Object, name) #define DEFINE_LISP_SYMBOL_END(name) \ - DEFINE_GDB_SYMBOL_END (LISP_INITIALLY (TAG_SYMOFFSET (i##name \ - * sizeof *lispsym))) + DEFINE_GDB_SYMBOL_END (LISP_INITIALLY (XLI_BUILTIN_LISPSYM (i##name))) #include "globals.h" @@ -1499,6 +1503,20 @@ gc_aset (Lisp_Object array, ptrdiff_t idx, Lisp_Object val) XVECTOR (array)->contents[idx] = val; } +/* True, since Qnil's representation is zero. Every place in the code + that assumes Qnil is zero should verify (NIL_IS_ZERO), to make it easy + to find such assumptions later if we change Qnil to be nonzero. */ +enum { NIL_IS_ZERO = XLI_BUILTIN_LISPSYM (iQnil) == 0 }; + +/* Set a Lisp_Object array V's SIZE entries to nil. */ +INLINE void +memsetnil (Lisp_Object *v, ptrdiff_t size) +{ + eassert (0 <= size); + verify (NIL_IS_ZERO); + memset (v, 0, size * sizeof *v); +} + /* If a struct is made to look like a vector, this macro returns the length of the shortest vector that would hold that struct. */ -- 2.39.5