From d6b6ac651c62e6a5cd9701d94419cfd53e95976e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= Date: Mon, 25 May 2020 18:05:23 -0300 Subject: [PATCH] Reduce the number of files probed when finding a lisp file. * src/lread.c (get-load-suffixes): Do not add any suffix to files that need to be loaded by the dynamic linker. (effective_load_path): Remove function. (load): Don't add any suffix if file ends in a suffix already. (openp): Add a parameter `add_eln_dir` that should be used when we desire the dir elt/eln-hash/ to be searched for each path in `path`. * src/lisp.h: Add new parameter to openp. * src/callproc.c: Add the new parameter to calls to openp(). * src/charset.c: Add the new parameter to calls to openp(). * src/emacs.c: Add the new parameter to calls to openp(). * src/image.c: Add the new parameter to calls to openp(). * src/process.c: Add the new parameter to calls to openp(). * src/w32.c: Add the new parameter to calls to openp(). * src/w32proc.c: Add the new parameter to calls to openp(). --- src/callproc.c | 2 +- src/charset.c | 2 +- src/emacs.c | 3 +- src/image.c | 4 +- src/lisp.h | 2 +- src/lread.c | 107 ++++++++++++++++++++++++++++++------------------- src/process.c | 2 +- src/w32.c | 3 +- src/w32proc.c | 3 +- 9 files changed, 78 insertions(+), 50 deletions(-) diff --git a/src/callproc.c b/src/callproc.c index 65c858393a..421e42de11 100644 --- a/src/callproc.c +++ b/src/callproc.c @@ -436,7 +436,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd, { int ok; - ok = openp (Vexec_path, args[0], Vexec_suffixes, &path, + ok = openp (Vexec_path, args[0], false, Vexec_suffixes, &path, make_fixnum (X_OK), false); if (ok < 0) report_file_error ("Searching for program", args[0]); diff --git a/src/charset.c b/src/charset.c index 8635aad3ed..da3ace743f 100644 --- a/src/charset.c +++ b/src/charset.c @@ -486,7 +486,7 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, ptrdiff_t count = SPECPDL_INDEX (); record_unwind_protect_nothing (); specbind (Qfile_name_handler_alist, Qnil); - fd = openp (Vcharset_map_path, mapfile, suffixes, NULL, Qnil, false); + fd = openp (Vcharset_map_path, mapfile, false, suffixes, NULL, Qnil, false); fp = fd < 0 ? 0 : fdopen (fd, "r"); if (!fp) { diff --git a/src/emacs.c b/src/emacs.c index cd4f7a0b28..35ae9d0e66 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -454,7 +454,8 @@ set_invocation_vars (char *argv0, char const *original_pwd) { Lisp_Object found; int yes = openp (Vexec_path, Vinvocation_name, - Vexec_suffixes, &found, make_fixnum (X_OK), false); + false, Vexec_suffixes, &found, make_fixnum (X_OK), + false); if (yes == 1) { /* Add /: to the front of the name diff --git a/src/image.c b/src/image.c index c8a192aaaf..80ef801913 100644 --- a/src/image.c +++ b/src/image.c @@ -508,7 +508,7 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) } /* Search bitmap-file-path for the file, if appropriate. */ - if (openp (Vx_bitmap_file_path, file, Qnil, &found, + if (openp (Vx_bitmap_file_path, file, false, Qnil, &found, make_fixnum (R_OK), false) < 0) return -1; @@ -2983,7 +2983,7 @@ image_find_image_fd (Lisp_Object file, int *pfd) Vx_bitmap_file_path); /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ - fd = openp (search_path, file, Qnil, &file_found, + fd = openp (search_path, file, false, Qnil, &file_found, pfd ? Qt : make_fixnum (R_OK), false); if (fd >= 0 || fd == -2) { diff --git a/src/lisp.h b/src/lisp.h index 52242791aa..5f921d58dc 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4094,7 +4094,7 @@ LOADHIST_ATTACH (Lisp_Object x) extern bool suffix_p (Lisp_Object, const char *); extern Lisp_Object save_match_data_load (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); -extern int openp (Lisp_Object, Lisp_Object, Lisp_Object, +extern int openp (Lisp_Object, Lisp_Object, bool, Lisp_Object, Lisp_Object *, Lisp_Object, bool); enum { S2N_IGNORE_TRAILING = 1 }; extern Lisp_Object string_to_number (char const *, int, ptrdiff_t *); diff --git a/src/lread.c b/src/lread.c index 46725d9b0f..aaf4ad1a37 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1056,33 +1056,25 @@ This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) { Lisp_Object exts = Vload_file_rep_suffixes; Lisp_Object suffix = XCAR (suffixes); - FOR_EACH_TAIL (exts) - lst = Fcons (concat2 (suffix, XCAR (exts)), lst); + if (false +#ifdef HAVE_MODULES + || strcmp (MODULES_SUFFIX, SSDATA (suffix)) == 0 +#ifdef MODULES_SECONDARY_SUFFIX + || strcmp (MODULES_SECONDARY_SUFFIX, SSDATA (suffix)) == 0 +#endif +#endif +#ifdef HAVE_NATIVE_COMP + || strcmp (NATIVE_ELISP_SUFFIX, SSDATA (suffix)) == 0 +#endif + ) + lst = Fcons (suffix, lst); + else + FOR_EACH_TAIL (exts) + lst = Fcons (concat2 (suffix, XCAR (exts)), lst); } return Fnreverse (lst); } -static Lisp_Object -effective_load_path (void) -{ -#ifndef HAVE_NATIVE_COMP - return Vload_path; -#else - Lisp_Object lp = Vload_path; - Lisp_Object new_lp = Qnil; - FOR_EACH_TAIL (lp) - { - Lisp_Object el = XCAR (lp); - new_lp = - Fcons (concat2 (Ffile_name_as_directory (el), - Vcomp_native_path_postfix), - new_lp); - new_lp = Fcons (el, new_lp); - } - return Fnreverse (new_lp); -#endif -} - /* Return true if STRING ends with SUFFIX. */ bool suffix_p (Lisp_Object string, const char *suffix) @@ -1217,6 +1209,9 @@ Return t if the file exists and loads successfully. */) #ifdef MODULES_SECONDARY_SUFFIX || suffix_p (file, MODULES_SECONDARY_SUFFIX) #endif +#endif +#ifdef HAVE_NATIVE_COMP + || suffix_p (file, NATIVE_ELISP_SUFFIX) #endif ) must_suffix = Qnil; @@ -1236,8 +1231,8 @@ Return t if the file exists and loads successfully. */) } fd = - openp (effective_load_path (), file, suffixes, &found, Qnil, - load_prefer_newer); + openp (Vload_path, file, true, suffixes, &found, Qnil, + load_prefer_newer); } if (fd == -1) @@ -1600,7 +1595,7 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) (Lisp_Object filename, Lisp_Object path, Lisp_Object suffixes, Lisp_Object predicate) { Lisp_Object file; - int fd = openp (path, filename, suffixes, &file, predicate, false); + int fd = openp (path, filename, Qnil, suffixes, &file, predicate, false); if (NILP (predicate) && fd >= 0) emacs_close (fd); return file; @@ -1611,6 +1606,9 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) On success, return a file descriptor (or 1 or -2 as described below). On failure, return -1 and set errno. + If ADD_ELN_DIR is nonzero, use the `comp-native-path-postfix' + variable to change the searched path if the suffix is .eln. + SUFFIXES is a list of strings containing possible suffixes. The empty suffix is automatically added if the list is empty. @@ -1633,8 +1631,9 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) or if a non-nil and non-t PREDICATE is specified. */ int -openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, - Lisp_Object *storeptr, Lisp_Object predicate, bool newer) +openp (Lisp_Object path, Lisp_Object str, bool add_eln_dir, + Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate, + bool newer) { ptrdiff_t fn_size = 100; char buf[100]; @@ -1643,7 +1642,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, ptrdiff_t want_length; Lisp_Object filename; Lisp_Object string, tail, encoded_fn, save_string; - ptrdiff_t max_suffix_len = 0; + ptrdiff_t max_extra_len = 0; int last_errno = ENOENT; int save_fd = -1; USE_SAFE_ALLOCA; @@ -1658,8 +1657,15 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, FOR_EACH_TAIL_SAFE (tail) { CHECK_STRING_CAR (tail); - max_suffix_len = max (max_suffix_len, - SBYTES (XCAR (tail))); + char * suf = SSDATA (XCAR (tail)); + ptrdiff_t len = SBYTES (XCAR (tail)); + if (add_eln_dir && strcmp (NATIVE_ELISP_SUFFIX, suf) == 0) + { + CHECK_STRING (Vcomp_native_path_postfix); + len += 2; + len += SBYTES (Vcomp_native_path_postfix); + } + max_extra_len = max (max_extra_len, len); } string = filename = encoded_fn = save_string = Qnil; @@ -1677,7 +1683,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, executable. */ FOR_EACH_TAIL_SAFE (path) { - ptrdiff_t baselen, prefixlen; + ptrdiff_t dirnamelen, prefixlen, basenamewext_len; if (EQ (path, just_use_str)) filename = str; @@ -1694,22 +1700,27 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, continue; } + /* Calculate maximum length of any filename made from this path element/specified file name and any possible suffix. */ - want_length = max_suffix_len + SBYTES (filename); + want_length = max_extra_len + SBYTES (filename); if (fn_size <= want_length) { fn_size = 100 + want_length; fn = SAFE_ALLOCA (fn_size); } + Lisp_Object dirnamewslash = Ffile_name_directory (filename); + Lisp_Object basenamewext = Ffile_name_nondirectory (filename); + /* Copy FILENAME's data to FN but remove starting /: if any. */ - prefixlen = ((SCHARS (filename) > 2 - && SREF (filename, 0) == '/' - && SREF (filename, 1) == ':') + prefixlen = ((SCHARS (dirnamewslash) > 2 + && SREF (dirnamewslash, 0) == '/' + && SREF (dirnamewslash, 1) == ':') ? 2 : 0); - baselen = SBYTES (filename) - prefixlen; - memcpy (fn, SDATA (filename) + prefixlen, baselen); + dirnamelen = SBYTES (dirnamewslash) - prefixlen; + basenamewext_len = SBYTES (basenamewext); + memcpy (fn, SDATA (dirnamewslash) + prefixlen, dirnamelen); /* Loop over suffixes. */ AUTO_LIST1 (empty_string_only, empty_unibyte_string); @@ -1719,10 +1730,24 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, Lisp_Object suffix = XCAR (tail); ptrdiff_t fnlen, lsuffix = SBYTES (suffix); Lisp_Object handler; + bool add_native_comp_dir = add_eln_dir + && (strcmp (SSDATA (suffix), NATIVE_ELISP_SUFFIX) == 0); + ptrdiff_t lmiddledir = add_native_comp_dir + ? SBYTES (Vcomp_native_path_postfix) + 1 : 0; + + if (add_native_comp_dir) + { + memcpy (fn + dirnamelen, SDATA (Vcomp_native_path_postfix), + lmiddledir - 1); + fn[dirnamelen+(lmiddledir-1)] = '/'; + } - /* Make complete filename by appending SUFFIX. */ - memcpy (fn + baselen, SDATA (suffix), lsuffix + 1); - fnlen = baselen + lsuffix; + memcpy (fn + dirnamelen + lmiddledir, SDATA (basenamewext), + basenamewext_len); + /* Make complete filename by appending SUFFIX. */ + memcpy (fn + dirnamelen + lmiddledir + basenamewext_len, + SDATA (suffix), lsuffix + 1); + fnlen = dirnamelen + lmiddledir + basenamewext_len + lsuffix; /* Check that the file exists and is not a directory. */ /* We used to only check for handlers on non-absolute file names: diff --git a/src/process.c b/src/process.c index 6e5bcf307a..e092fa0a0c 100644 --- a/src/process.c +++ b/src/process.c @@ -1903,7 +1903,7 @@ usage: (make-process &rest ARGS) */) && IS_DEVICE_SEP (SREF (program, 1)))) { tem = Qnil; - openp (Vexec_path, program, Vexec_suffixes, &tem, + openp (Vexec_path, program, false, Vexec_suffixes, &tem, make_fixnum (X_OK), false); if (NILP (tem)) report_file_error ("Searching for program", program); diff --git a/src/w32.c b/src/w32.c index 38bbc49656..3e71d0d383 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10187,7 +10187,8 @@ check_windows_init_file (void) need to ENCODE_FILE here, but we do need to convert the file names from UTF-8 to ANSI. */ init_file = build_string ("term/w32-win"); - fd = openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0); + fd = openp (Vload_path, init_file, true, Fget_load_suffixes (), NULL, + Qnil, 0); if (fd < 0) { Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil); diff --git a/src/w32proc.c b/src/w32proc.c index 16e32e4c58..4aa4c9fa0a 100644 --- a/src/w32proc.c +++ b/src/w32proc.c @@ -1918,7 +1918,8 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp) { program = build_string (cmdname); full = Qnil; - openp (Vexec_path, program, Vexec_suffixes, &full, make_fixnum (X_OK), 0); + openp (Vexec_path, program, false, Vexec_suffixes, &full, + make_fixnum (X_OK), 0); if (NILP (full)) { errno = EINVAL; -- 2.20.1