diff options
| author | Nicolás Bértolo | 2020-05-25 18:05:23 -0300 |
|---|---|---|
| committer | Andrea Corallo | 2020-06-06 21:52:20 +0200 |
| commit | e38678b268c2a3f77d1fa32a55706fb9e077405c (patch) | |
| tree | f78ffbd5da5b17b5a827d18ee00b08ce59949cbf /src | |
| parent | ee3df1483a9e733c27629da7bcf515789df52ef8 (diff) | |
| download | emacs-e38678b268c2a3f77d1fa32a55706fb9e077405c.tar.gz emacs-e38678b268c2a3f77d1fa32a55706fb9e077405c.zip | |
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.
(effective_load_path): Remove function.
(openp_add_middle_dir_to_suffixes): Add helper function to create
pairs of middle directories and suffixes.
(openp_max_middledir_and_suffix_len): Add helper function to count the
number of bytes needed to store the middle directory and suffix.
(openp_fill_filename_buffer): Add helper function to copy middle
directory, basename and suffix to the filename buffer.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lread.c | 203 |
1 files changed, 154 insertions, 49 deletions
diff --git a/src/lread.c b/src/lread.c index 192c7ba773a..a3e8d07c563 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -1056,31 +1056,27 @@ This uses the variables `load-suffixes' and `load-file-rep-suffixes'. */) | |||
| 1056 | { | 1056 | { |
| 1057 | Lisp_Object exts = Vload_file_rep_suffixes; | 1057 | Lisp_Object exts = Vload_file_rep_suffixes; |
| 1058 | Lisp_Object suffix = XCAR (suffixes); | 1058 | Lisp_Object suffix = XCAR (suffixes); |
| 1059 | FOR_EACH_TAIL (exts) | 1059 | bool native_code_suffix = |
| 1060 | lst = Fcons (concat2 (suffix, XCAR (exts)), lst); | 1060 | NATIVE_COMP_FLAG |
| 1061 | } | 1061 | && strcmp (NATIVE_ELISP_SUFFIX, SSDATA (suffix)) == 0; |
| 1062 | return Fnreverse (lst); | ||
| 1063 | } | ||
| 1064 | 1062 | ||
| 1065 | static Lisp_Object | 1063 | #ifdef HAVE_MODULES |
| 1066 | effective_load_path (void) | 1064 | native_code_suffix = |
| 1067 | { | 1065 | native_code_suffix || strcmp (MODULES_SUFFIX, SSDATA (suffix)) == 0; |
| 1068 | #ifndef HAVE_NATIVE_COMP | 1066 | #ifdef MODULES_SECONDARY_SUFFIX |
| 1069 | return Vload_path; | 1067 | native_code_suffix = |
| 1070 | #else | 1068 | native_code_suffix |
| 1071 | Lisp_Object lp = Vload_path; | 1069 | || strcmp (MODULES_SECONDARY_SUFFIX, SSDATA (suffix)) == 0; |
| 1072 | Lisp_Object new_lp = Qnil; | ||
| 1073 | FOR_EACH_TAIL (lp) | ||
| 1074 | { | ||
| 1075 | Lisp_Object el = XCAR (lp); | ||
| 1076 | new_lp = | ||
| 1077 | Fcons (concat2 (Ffile_name_as_directory (el), | ||
| 1078 | Vcomp_native_path_postfix), | ||
| 1079 | new_lp); | ||
| 1080 | new_lp = Fcons (el, new_lp); | ||
| 1081 | } | ||
| 1082 | return Fnreverse (new_lp); | ||
| 1083 | #endif | 1070 | #endif |
| 1071 | #endif | ||
| 1072 | |||
| 1073 | if (native_code_suffix) | ||
| 1074 | lst = Fcons (suffix, lst); | ||
| 1075 | else | ||
| 1076 | FOR_EACH_TAIL (exts) | ||
| 1077 | lst = Fcons (concat2 (suffix, XCAR (exts)), lst); | ||
| 1078 | } | ||
| 1079 | return Fnreverse (lst); | ||
| 1084 | } | 1080 | } |
| 1085 | 1081 | ||
| 1086 | /* Return true if STRING ends with SUFFIX. */ | 1082 | /* Return true if STRING ends with SUFFIX. */ |
| @@ -1218,7 +1214,7 @@ Return t if the file exists and loads successfully. */) | |||
| 1218 | || suffix_p (file, MODULES_SECONDARY_SUFFIX) | 1214 | || suffix_p (file, MODULES_SECONDARY_SUFFIX) |
| 1219 | #endif | 1215 | #endif |
| 1220 | #endif | 1216 | #endif |
| 1221 | ) | 1217 | || (NATIVE_COMP_FLAG && suffix_p (file, NATIVE_ELISP_SUFFIX))) |
| 1222 | must_suffix = Qnil; | 1218 | must_suffix = Qnil; |
| 1223 | /* Don't insist on adding a suffix | 1219 | /* Don't insist on adding a suffix |
| 1224 | if the argument includes a directory name. */ | 1220 | if the argument includes a directory name. */ |
| @@ -1236,8 +1232,7 @@ Return t if the file exists and loads successfully. */) | |||
| 1236 | } | 1232 | } |
| 1237 | 1233 | ||
| 1238 | fd = | 1234 | fd = |
| 1239 | openp (effective_load_path (), file, suffixes, &found, Qnil, | 1235 | openp (Vload_path, file, suffixes, &found, Qnil, load_prefer_newer); |
| 1240 | load_prefer_newer); | ||
| 1241 | } | 1236 | } |
| 1242 | 1237 | ||
| 1243 | if (fd == -1) | 1238 | if (fd == -1) |
| @@ -1612,6 +1607,114 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) | |||
| 1612 | return file; | 1607 | return file; |
| 1613 | } | 1608 | } |
| 1614 | 1609 | ||
| 1610 | /* This function turns a list of suffixes into a list of middle dirs | ||
| 1611 | and suffixes. If the suffix is not NATIVE_ELISP_SUFFIX then its | ||
| 1612 | suffix is nil and it is added to the list as is. Instead, if it | ||
| 1613 | suffix is NATIVE_ELISP_SUFFIX then two elements are added to the | ||
| 1614 | list. The first one has middledir equal to nil and the second uses | ||
| 1615 | comp-native-path-postfix as middledir. This is because we'd like | ||
| 1616 | to search for dir/foo.eln before dir/middledir/foo.eln. | ||
| 1617 | |||
| 1618 | For example, it turns this: | ||
| 1619 | |||
| 1620 | (".eln" ".elc" ".elc.gz" ".el" ".el.gz") | ||
| 1621 | |||
| 1622 | into this: | ||
| 1623 | |||
| 1624 | ((nil . ".eln") | ||
| 1625 | (comp-native-path-postfix . ".eln") | ||
| 1626 | (nil . ".elc") | ||
| 1627 | (nil . ".elc.gz") | ||
| 1628 | (nil . ".el") | ||
| 1629 | (nil . ".el.gz")) | ||
| 1630 | */ | ||
| 1631 | static Lisp_Object | ||
| 1632 | openp_add_middle_dir_to_suffixes (Lisp_Object suffixes) | ||
| 1633 | { | ||
| 1634 | Lisp_Object tail = suffixes; | ||
| 1635 | Lisp_Object extended_suf = Qnil; | ||
| 1636 | FOR_EACH_TAIL_SAFE (tail) | ||
| 1637 | { | ||
| 1638 | #ifdef HAVE_NATIVE_COMP | ||
| 1639 | CHECK_STRING_CAR (tail); | ||
| 1640 | char * suf = SSDATA (XCAR (tail)); | ||
| 1641 | if (strcmp (NATIVE_ELISP_SUFFIX, suf) == 0) | ||
| 1642 | { | ||
| 1643 | CHECK_STRING (Vcomp_native_path_postfix); | ||
| 1644 | /* Here we add them in the opposite order so that nreverse | ||
| 1645 | corrects it. */ | ||
| 1646 | extended_suf = Fcons (Fcons (Qnil, XCAR (tail)), extended_suf); | ||
| 1647 | extended_suf = Fcons (Fcons (Vcomp_native_path_postfix, XCAR (tail)), | ||
| 1648 | extended_suf); | ||
| 1649 | } | ||
| 1650 | else | ||
| 1651 | #endif | ||
| 1652 | extended_suf = Fcons (Fcons (Qnil, XCAR (tail)), extended_suf); | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | suffixes = Fnreverse (extended_suf); | ||
| 1656 | return suffixes; | ||
| 1657 | } | ||
| 1658 | |||
| 1659 | /* This function takes a list of middledirs and suffixes and returns | ||
| 1660 | the maximum buffer space that this part of the filename will | ||
| 1661 | need. */ | ||
| 1662 | static ptrdiff_t | ||
| 1663 | openp_max_middledir_and_suffix_len (Lisp_Object middledir_and_suffixes) | ||
| 1664 | { | ||
| 1665 | ptrdiff_t max_extra_len = 0; | ||
| 1666 | Lisp_Object tail = middledir_and_suffixes; | ||
| 1667 | FOR_EACH_TAIL_SAFE (tail) | ||
| 1668 | { | ||
| 1669 | Lisp_Object middledir_and_suffix = XCAR (tail); | ||
| 1670 | Lisp_Object middledir = XCAR (middledir_and_suffix); | ||
| 1671 | Lisp_Object suffix = XCDR (middledir_and_suffix); | ||
| 1672 | ptrdiff_t len = SBYTES (suffix); | ||
| 1673 | if (!NILP (middledir)) | ||
| 1674 | len += 2 + SBYTES (middledir); /* Add two slashes. */ | ||
| 1675 | max_extra_len = max (max_extra_len, len); | ||
| 1676 | } | ||
| 1677 | return max_extra_len; | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | /* This function completes the FN buffer with the middledir, | ||
| 1681 | basenameme, and suffix. It takes the directory length in DIRNAME, | ||
| 1682 | but it requires that it has been copied already to the start of | ||
| 1683 | the buffer. | ||
| 1684 | |||
| 1685 | After this function the FN buffer will be (depending on middledir) | ||
| 1686 | dirname/middledir/basename.suffix | ||
| 1687 | or | ||
| 1688 | dirname/basename.suffix | ||
| 1689 | */ | ||
| 1690 | static ptrdiff_t | ||
| 1691 | openp_fill_filename_buffer (char *fn, ptrdiff_t dirnamelen, | ||
| 1692 | Lisp_Object basenamewext, | ||
| 1693 | Lisp_Object middledir_and_suffix) | ||
| 1694 | { | ||
| 1695 | Lisp_Object middledir = XCAR (middledir_and_suffix); | ||
| 1696 | Lisp_Object suffix = XCDR (middledir_and_suffix); | ||
| 1697 | ptrdiff_t basenamewext_len = SBYTES (basenamewext); | ||
| 1698 | ptrdiff_t fnlen, lsuffix = SBYTES (suffix); | ||
| 1699 | ptrdiff_t lmiddledir = 0; | ||
| 1700 | if (!NILP (middledir)) | ||
| 1701 | { | ||
| 1702 | /* Add 1 for the slash. */ | ||
| 1703 | lmiddledir = SBYTES (middledir) + 1; | ||
| 1704 | memcpy (fn + dirnamelen, SDATA (middledir), | ||
| 1705 | lmiddledir - 1); | ||
| 1706 | fn[dirnamelen + (lmiddledir - 1)] = '/'; | ||
| 1707 | } | ||
| 1708 | |||
| 1709 | memcpy (fn + dirnamelen + lmiddledir, SDATA (basenamewext), | ||
| 1710 | basenamewext_len); | ||
| 1711 | /* Make complete filename by appending SUFFIX. */ | ||
| 1712 | memcpy (fn + dirnamelen + lmiddledir + basenamewext_len, | ||
| 1713 | SDATA (suffix), lsuffix + 1); | ||
| 1714 | fnlen = dirnamelen + lmiddledir + basenamewext_len + lsuffix; | ||
| 1715 | return fnlen; | ||
| 1716 | } | ||
| 1717 | |||
| 1615 | /* Search for a file whose name is STR, looking in directories | 1718 | /* Search for a file whose name is STR, looking in directories |
| 1616 | in the Lisp list PATH, and trying suffixes from SUFFIX. | 1719 | in the Lisp list PATH, and trying suffixes from SUFFIX. |
| 1617 | On success, return a file descriptor (or 1 or -2 as described below). | 1720 | On success, return a file descriptor (or 1 or -2 as described below). |
| @@ -1649,7 +1752,8 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1649 | ptrdiff_t want_length; | 1752 | ptrdiff_t want_length; |
| 1650 | Lisp_Object filename; | 1753 | Lisp_Object filename; |
| 1651 | Lisp_Object string, tail, encoded_fn, save_string; | 1754 | Lisp_Object string, tail, encoded_fn, save_string; |
| 1652 | ptrdiff_t max_suffix_len = 0; | 1755 | Lisp_Object middledir_and_suffixes; |
| 1756 | ptrdiff_t max_extra_len = 0; | ||
| 1653 | int last_errno = ENOENT; | 1757 | int last_errno = ENOENT; |
| 1654 | int save_fd = -1; | 1758 | int save_fd = -1; |
| 1655 | USE_SAFE_ALLOCA; | 1759 | USE_SAFE_ALLOCA; |
| @@ -1660,13 +1764,9 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1660 | 1764 | ||
| 1661 | CHECK_STRING (str); | 1765 | CHECK_STRING (str); |
| 1662 | 1766 | ||
| 1663 | tail = suffixes; | 1767 | middledir_and_suffixes = openp_add_middle_dir_to_suffixes (suffixes); |
| 1664 | FOR_EACH_TAIL_SAFE (tail) | 1768 | |
| 1665 | { | 1769 | max_extra_len = openp_max_middledir_and_suffix_len (middledir_and_suffixes); |
| 1666 | CHECK_STRING_CAR (tail); | ||
| 1667 | max_suffix_len = max (max_suffix_len, | ||
| 1668 | SBYTES (XCAR (tail))); | ||
| 1669 | } | ||
| 1670 | 1770 | ||
| 1671 | string = filename = encoded_fn = save_string = Qnil; | 1771 | string = filename = encoded_fn = save_string = Qnil; |
| 1672 | 1772 | ||
| @@ -1683,7 +1783,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1683 | executable. */ | 1783 | executable. */ |
| 1684 | FOR_EACH_TAIL_SAFE (path) | 1784 | FOR_EACH_TAIL_SAFE (path) |
| 1685 | { | 1785 | { |
| 1686 | ptrdiff_t baselen, prefixlen; | 1786 | ptrdiff_t dirnamelen, prefixlen; |
| 1687 | 1787 | ||
| 1688 | if (EQ (path, just_use_str)) | 1788 | if (EQ (path, just_use_str)) |
| 1689 | filename = str; | 1789 | filename = str; |
| @@ -1700,35 +1800,40 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, | |||
| 1700 | continue; | 1800 | continue; |
| 1701 | } | 1801 | } |
| 1702 | 1802 | ||
| 1803 | |||
| 1703 | /* Calculate maximum length of any filename made from | 1804 | /* Calculate maximum length of any filename made from |
| 1704 | this path element/specified file name and any possible suffix. */ | 1805 | this path element/specified file name and any possible suffix. */ |
| 1705 | want_length = max_suffix_len + SBYTES (filename); | 1806 | want_length = max_extra_len + SBYTES (filename); |
| 1706 | if (fn_size <= want_length) | 1807 | if (fn_size <= want_length) |
| 1707 | { | 1808 | { |
| 1708 | fn_size = 100 + want_length; | 1809 | fn_size = 100 + want_length; |
| 1709 | fn = SAFE_ALLOCA (fn_size); | 1810 | fn = SAFE_ALLOCA (fn_size); |
| 1710 | } | 1811 | } |
| 1711 | 1812 | ||
| 1813 | Lisp_Object dirnamewslash = Ffile_name_directory (filename); | ||
| 1814 | Lisp_Object basenamewext = Ffile_name_nondirectory (filename); | ||
| 1815 | |||
| 1712 | /* Copy FILENAME's data to FN but remove starting /: if any. */ | 1816 | /* Copy FILENAME's data to FN but remove starting /: if any. */ |
| 1713 | prefixlen = ((SCHARS (filename) > 2 | 1817 | prefixlen = ((SCHARS (dirnamewslash) > 2 |
| 1714 | && SREF (filename, 0) == '/' | 1818 | && SREF (dirnamewslash, 0) == '/' |
| 1715 | && SREF (filename, 1) == ':') | 1819 | && SREF (dirnamewslash, 1) == ':') |
| 1716 | ? 2 : 0); | 1820 | ? 2 : 0); |
| 1717 | baselen = SBYTES (filename) - prefixlen; | 1821 | dirnamelen = SBYTES (dirnamewslash) - prefixlen; |
| 1718 | memcpy (fn, SDATA (filename) + prefixlen, baselen); | 1822 | memcpy (fn, SDATA (dirnamewslash) + prefixlen, dirnamelen); |
| 1719 | 1823 | ||
| 1720 | /* Loop over suffixes. */ | 1824 | /* Loop over middledir_and_suffixes. */ |
| 1721 | AUTO_LIST1 (empty_string_only, empty_unibyte_string); | 1825 | AUTO_LIST1 (empty_string_only, Fcons (Qnil, empty_unibyte_string)); |
| 1722 | tail = NILP (suffixes) ? empty_string_only : suffixes; | 1826 | tail = NILP (middledir_and_suffixes) ? empty_string_only |
| 1827 | : middledir_and_suffixes; | ||
| 1723 | FOR_EACH_TAIL_SAFE (tail) | 1828 | FOR_EACH_TAIL_SAFE (tail) |
| 1724 | { | 1829 | { |
| 1725 | Lisp_Object suffix = XCAR (tail); | 1830 | Lisp_Object middledir_and_suffix = XCAR (tail); |
| 1726 | ptrdiff_t fnlen, lsuffix = SBYTES (suffix); | 1831 | Lisp_Object suffix = XCDR (middledir_and_suffix); |
| 1727 | Lisp_Object handler; | 1832 | Lisp_Object handler; |
| 1728 | 1833 | ||
| 1729 | /* Make complete filename by appending SUFFIX. */ | 1834 | ptrdiff_t fnlen = openp_fill_filename_buffer (fn, dirnamelen, |
| 1730 | memcpy (fn + baselen, SDATA (suffix), lsuffix + 1); | 1835 | basenamewext, |
| 1731 | fnlen = baselen + lsuffix; | 1836 | middledir_and_suffix); |
| 1732 | 1837 | ||
| 1733 | /* Check that the file exists and is not a directory. */ | 1838 | /* Check that the file exists and is not a directory. */ |
| 1734 | /* We used to only check for handlers on non-absolute file names: | 1839 | /* We used to only check for handlers on non-absolute file names: |