emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 2335704: directory-files cleanup and speed tweaking


From: Paul Eggert
Subject: [Emacs-diffs] master 2335704: directory-files cleanup and speed tweaking
Date: Mon, 16 Sep 2019 16:55:27 -0400 (EDT)

branch: master
commit 2335704fccc2a5088c864bea1f10b4f0ef788e6b
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    directory-files cleanup and speed tweaking
    
    * src/dired.c (directory_files_internal):
    Check ‘match’ before doing anything heavyweight.
    Move decls closer to use.
    Remove obsolete comments about GC.
    No need to encode ‘directory’ or to call multibyte_chars_in_text.
    Remove no-longer-needed bug check.
    Skip finalname construction if file_attributes fails.
---
 src/dired.c | 129 +++++++++++++++++++++++-------------------------------------
 1 file changed, 49 insertions(+), 80 deletions(-)

diff --git a/src/dired.c b/src/dired.c
index cec79ab..5fc6ccd 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -167,28 +167,19 @@ directory_files_internal (Lisp_Object directory, 
Lisp_Object full,
                          Lisp_Object match, Lisp_Object nosort, bool attrs,
                          Lisp_Object id_format)
 {
-  ptrdiff_t directory_nbytes;
-  Lisp_Object list, dirfilename, encoded_directory;
-  bool needsep = 0;
-  ptrdiff_t count = SPECPDL_INDEX ();
-#ifdef WINDOWSNT
-  Lisp_Object w32_save = Qnil;
-#endif
+  if (!NILP (match))
+    CHECK_STRING (match);
 
   /* Don't let the compiler optimize away all copies of DIRECTORY,
      which would break GC; see Bug#16986.  */
   Lisp_Object volatile directory_volatile = directory;
 
-  /* Because of file name handlers, these functions might call
-     Ffuncall, and cause a GC.  */
-  list = encoded_directory = dirfilename = Qnil;
-  dirfilename = Fdirectory_file_name (directory);
+  Lisp_Object dirfilename = Fdirectory_file_name (directory);
 
   /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
      run_pre_post_conversion_on_str which calls Lisp directly and
      indirectly.  */
   Lisp_Object encoded_dirfilename = ENCODE_FILE (dirfilename);
-  encoded_directory = ENCODE_FILE (directory);
 
   int fd;
   DIR *d = open_directory (dirfilename, encoded_dirfilename, &fd);
@@ -196,9 +187,11 @@ directory_files_internal (Lisp_Object directory, 
Lisp_Object full,
   /* Unfortunately, we can now invoke expand-file-name and
      file-attributes on filenames, both of which can throw, so we must
      do a proper unwind-protect.  */
+  ptrdiff_t count = SPECPDL_INDEX ();
   record_unwind_protect_ptr (directory_files_internal_unwind, d);
 
 #ifdef WINDOWSNT
+  Lisp_Object w32_save = Qnil;
   if (attrs)
     {
       /* Do this only once to avoid doing it (in w32.c:stat) for each
@@ -218,89 +211,63 @@ directory_files_internal (Lisp_Object directory, 
Lisp_Object full,
     }
 #endif
 
-  directory_nbytes = SBYTES (directory);
+  ptrdiff_t directory_nbytes = SBYTES (directory);
   re_match_object = Qt;
 
   /* Decide whether we need to add a directory separator.  */
-  if (directory_nbytes == 0
-      || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)))
-    needsep = 1;
+  bool needsep = (directory_nbytes == 0
+                 || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1)));
 
   /* Windows users want case-insensitive wildcards.  */
-  Lisp_Object case_table =
+  Lisp_Object case_table = Qnil;
 #ifdef WINDOWSNT
-    BVAR (&buffer_defaults, case_canon_table)
-#else
-    Qnil
+  case_table = BVAR (&buffer_defaults, case_canon_table);
 #endif
-    ;
 
-  if (!NILP (match))
-    CHECK_STRING (match);
-
-  /* Loop reading directory entries.  */
+  /* Read directory entries and accumulate them into LIST.  */
+  Lisp_Object list = Qnil;
   for (struct dirent *dp; (dp = read_dirent (d, directory)); )
     {
       ptrdiff_t len = dirent_namelen (dp);
       Lisp_Object name = make_unibyte_string (dp->d_name, len);
       Lisp_Object finalname = name;
 
-      /* Note: DECODE_FILE can GC; it should protect its argument,
-        though.  */
+      /* This can GC.  */
       name = DECODE_FILE (name);
-      len = SBYTES (name);
 
-      /* Now that we have unwind_protect in place, we might as well
-        allow matching to be interrupted.  */
       maybe_quit ();
 
-      bool wanted = (NILP (match) ||
-                     fast_string_match_internal (
-                       match, name, case_table) >= 0);
+      if (!NILP (match)
+         && fast_string_match_internal (match, name, case_table) < 0)
+       continue;
 
-      if (wanted)
+      Lisp_Object fileattrs;
+      if (attrs)
        {
-         if (!NILP (full))
-           {
-             Lisp_Object fullname;
-             ptrdiff_t nbytes = len + directory_nbytes + needsep;
-             ptrdiff_t nchars;
-
-             fullname = make_uninit_multibyte_string (nbytes, nbytes);
-             memcpy (SDATA (fullname), SDATA (directory),
-                     directory_nbytes);
-
-             if (needsep)
-               SSET (fullname, directory_nbytes, DIRECTORY_SEP);
-
-             memcpy (SDATA (fullname) + directory_nbytes + needsep,
-                     SDATA (name), len);
-
-             nchars = multibyte_chars_in_text (SDATA (fullname), nbytes);
-
-             /* Some bug somewhere.  */
-             if (nchars > nbytes)
-               emacs_abort ();
-
-             STRING_SET_CHARS (fullname, nchars);
-             if (nchars == nbytes)
-               STRING_SET_UNIBYTE (fullname);
-
-             finalname = fullname;
-           }
-         else
-           finalname = name;
+         fileattrs = file_attributes (fd, dp->d_name, directory, name,
+                                      id_format);
+         if (NILP (fileattrs))
+           continue;
+       }
 
-         if (attrs)
-           {
-             Lisp_Object fileattrs
-               = file_attributes (fd, dp->d_name, directory, name, id_format);
-             if (!NILP (fileattrs))
-               list = Fcons (Fcons (finalname, fileattrs), list);
-           }
-         else
-           list = Fcons (finalname, list);
+      if (!NILP (full))
+       {
+         ptrdiff_t name_nbytes = SBYTES (name);
+         ptrdiff_t nbytes = directory_nbytes + needsep + name_nbytes;
+         ptrdiff_t nchars = SCHARS (directory) + needsep + SCHARS (name);
+         finalname = make_uninit_multibyte_string (nchars, nbytes);
+         if (nchars == nbytes)
+           STRING_SET_UNIBYTE (finalname);
+         memcpy (SDATA (finalname), SDATA (directory), directory_nbytes);
+         if (needsep)
+           SSET (finalname, directory_nbytes, DIRECTORY_SEP);
+         memcpy (SDATA (finalname) + directory_nbytes + needsep,
+                 SDATA (name), name_nbytes);
        }
+      else
+       finalname = name;
+
+      list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
     }
 
   closedir (d);
@@ -330,14 +297,14 @@ If MATCH is non-nil, mention only file names that match 
the regexp MATCH.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
  Otherwise, the list returned is sorted with `string-lessp'.
  NOSORT is useful if you plan to sort the result yourself.  */)
-  (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object 
nosort)
+  (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
+   Lisp_Object nosort)
 {
-  Lisp_Object handler;
   directory = Fexpand_file_name (directory, Qnil);
 
   /* If the file name has special constructs in it,
      call the corresponding file name handler.  */
-  handler = Ffind_file_name_handler (directory, Qdirectory_files);
+  Lisp_Object handler = Ffind_file_name_handler (directory, Qdirectory_files);
   if (!NILP (handler))
     return call5 (handler, Qdirectory_files, directory,
                   full, match, nosort);
@@ -365,14 +332,15 @@ ID-FORMAT specifies the preferred format of attributes 
uid and gid, see
 `file-attributes' for further documentation.
 On MS-Windows, performance depends on `w32-get-true-file-attributes',
 which see.  */)
-  (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object 
nosort, Lisp_Object id_format)
+  (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
+   Lisp_Object nosort, Lisp_Object id_format)
 {
-  Lisp_Object handler;
   directory = Fexpand_file_name (directory, Qnil);
 
   /* If the file name has special constructs in it,
      call the corresponding file name handler.  */
-  handler = Ffind_file_name_handler (directory, 
Qdirectory_files_and_attributes);
+  Lisp_Object handler
+    = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
   if (!NILP (handler))
     return call6 (handler, Qdirectory_files_and_attributes,
                   directory, full, match, nosort, id_format);
@@ -1032,7 +1000,8 @@ file_attributes (int fd, char const *name,
                INT_TO_INTEGER (s.st_dev));
 }
 
-DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, 
Sfile_attributes_lessp, 2, 2, 0,
+DEFUN ("file-attributes-lessp", Ffile_attributes_lessp,
+       Sfile_attributes_lessp, 2, 2, 0,
        doc: /* Return t if first arg file attributes list is less than second.
 Comparison is in lexicographic order and case is significant.  */)
   (Lisp_Object f1, Lisp_Object f2)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]