From e19d43350e30bd5816dd8fd33c6770351ea902b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20B=C3=A9rtolo?= <nicolasbertolo@gmail.com>
Date: Sat, 23 May 2020 18:49:52 -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    | 103 +++++++++++++++++++++++++++++--------------------
 src/process.c  |   2 +-
 src/w32.c      |   2 +-
 src/w32proc.c  |   2 +-
 9 files changed, 72 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 b7c89b44ec..ce7b210c6f 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -449,7 +449,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 3e7e51f839..0bf2cfd741 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4096,7 +4096,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 01f359ca58..9c3a682bb7 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1056,33 +1056,25 @@ DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0,
     {
       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 @@ DEFUN ("load", Fload, Sload, 1, 5, 0,
 #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 @@ DEFUN ("load", Fload, Sload, 1, 5, 0,
 	}
 
       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 @@ DEFUN ("locate-file-internal", Flocate_file_internal, Slocate_file_internal, 2,
   (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;
@@ -1633,8 +1628,9 @@ DEFUN ("locate-file-internal", Flocate_file_internal, Slocate_file_internal, 2,
    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 fix_load_paths,
+       Lisp_Object suffixes, Lisp_Object *storeptr, Lisp_Object predicate,
+       bool newer)
 {
   ptrdiff_t fn_size = 100;
   char buf[100];
@@ -1643,7 +1639,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 +1654,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 (fix_load_paths && 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 +1680,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 +1697,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 +1727,23 @@ 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 = fix_load_paths &&
+          (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 @@ DEFUN ("make-process", Fmake_process, Smake_process, 0, MANY, 0,
 	       && 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 fd1f0e059e..3622a555d7 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -10177,7 +10177,7 @@ 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..85f2ccf016 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -1918,7 +1918,7 @@ 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.25.1.windows.1

