diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 319 |
1 files changed, 217 insertions, 102 deletions
diff --git a/src/alloc.c b/src/alloc.c index 1c6b664b220..a35b48cfb22 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -104,6 +104,26 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 104 | #include "w32heap.h" /* for sbrk */ | 104 | #include "w32heap.h" /* for sbrk */ |
| 105 | #endif | 105 | #endif |
| 106 | 106 | ||
| 107 | /* MALLOC_SIZE_NEAR (N) is a good number to pass to malloc when | ||
| 108 | allocating a block of memory with size close to N bytes. | ||
| 109 | For best results N should be a power of 2. | ||
| 110 | |||
| 111 | When calculating how much memory to allocate, GNU malloc (SIZE) | ||
| 112 | adds sizeof (size_t) to SIZE for internal overhead, and then rounds | ||
| 113 | up to a multiple of MALLOC_ALIGNMENT. Emacs can improve | ||
| 114 | performance a bit on GNU platforms by arranging for the resulting | ||
| 115 | size to be a power of two. This heuristic is good for glibc 2.0 | ||
| 116 | (1997) through at least glibc 2.31 (2020), and does not affect | ||
| 117 | correctness on other platforms. */ | ||
| 118 | |||
| 119 | #define MALLOC_SIZE_NEAR(n) \ | ||
| 120 | (ROUNDUP (max (n, sizeof (size_t)), MALLOC_ALIGNMENT) - sizeof (size_t)) | ||
| 121 | #ifdef __i386 | ||
| 122 | enum { MALLOC_ALIGNMENT = 16 }; | ||
| 123 | #else | ||
| 124 | enum { MALLOC_ALIGNMENT = max (2 * sizeof (size_t), alignof (long double)) }; | ||
| 125 | #endif | ||
| 126 | |||
| 107 | #ifdef DOUG_LEA_MALLOC | 127 | #ifdef DOUG_LEA_MALLOC |
| 108 | 128 | ||
| 109 | /* Specify maximum number of areas to mmap. It would be nice to use a | 129 | /* Specify maximum number of areas to mmap. It would be nice to use a |
| @@ -694,7 +714,7 @@ malloc_unblock_input (void) | |||
| 694 | malloc_probe (size); \ | 714 | malloc_probe (size); \ |
| 695 | } while (0) | 715 | } while (0) |
| 696 | 716 | ||
| 697 | static void *lmalloc (size_t) ATTRIBUTE_MALLOC_SIZE ((1)); | 717 | static void *lmalloc (size_t, bool) ATTRIBUTE_MALLOC_SIZE ((1)); |
| 698 | static void *lrealloc (void *, size_t); | 718 | static void *lrealloc (void *, size_t); |
| 699 | 719 | ||
| 700 | /* Like malloc but check for no memory and block interrupt input. */ | 720 | /* Like malloc but check for no memory and block interrupt input. */ |
| @@ -705,7 +725,7 @@ xmalloc (size_t size) | |||
| 705 | void *val; | 725 | void *val; |
| 706 | 726 | ||
| 707 | MALLOC_BLOCK_INPUT; | 727 | MALLOC_BLOCK_INPUT; |
| 708 | val = lmalloc (size); | 728 | val = lmalloc (size, false); |
| 709 | MALLOC_UNBLOCK_INPUT; | 729 | MALLOC_UNBLOCK_INPUT; |
| 710 | 730 | ||
| 711 | if (!val && size) | 731 | if (!val && size) |
| @@ -722,12 +742,11 @@ xzalloc (size_t size) | |||
| 722 | void *val; | 742 | void *val; |
| 723 | 743 | ||
| 724 | MALLOC_BLOCK_INPUT; | 744 | MALLOC_BLOCK_INPUT; |
| 725 | val = lmalloc (size); | 745 | val = lmalloc (size, true); |
| 726 | MALLOC_UNBLOCK_INPUT; | 746 | MALLOC_UNBLOCK_INPUT; |
| 727 | 747 | ||
| 728 | if (!val && size) | 748 | if (!val && size) |
| 729 | memory_full (size); | 749 | memory_full (size); |
| 730 | memset (val, 0, size); | ||
| 731 | MALLOC_PROBE (size); | 750 | MALLOC_PROBE (size); |
| 732 | return val; | 751 | return val; |
| 733 | } | 752 | } |
| @@ -743,7 +762,7 @@ xrealloc (void *block, size_t size) | |||
| 743 | /* We must call malloc explicitly when BLOCK is 0, since some | 762 | /* We must call malloc explicitly when BLOCK is 0, since some |
| 744 | reallocs don't do this. */ | 763 | reallocs don't do this. */ |
| 745 | if (! block) | 764 | if (! block) |
| 746 | val = lmalloc (size); | 765 | val = lmalloc (size, false); |
| 747 | else | 766 | else |
| 748 | val = lrealloc (block, size); | 767 | val = lrealloc (block, size); |
| 749 | MALLOC_UNBLOCK_INPUT; | 768 | MALLOC_UNBLOCK_INPUT; |
| @@ -939,7 +958,7 @@ void *lisp_malloc_loser EXTERNALLY_VISIBLE; | |||
| 939 | #endif | 958 | #endif |
| 940 | 959 | ||
| 941 | static void * | 960 | static void * |
| 942 | lisp_malloc (size_t nbytes, enum mem_type type) | 961 | lisp_malloc (size_t nbytes, bool clearit, enum mem_type type) |
| 943 | { | 962 | { |
| 944 | register void *val; | 963 | register void *val; |
| 945 | 964 | ||
| @@ -949,7 +968,7 @@ lisp_malloc (size_t nbytes, enum mem_type type) | |||
| 949 | allocated_mem_type = type; | 968 | allocated_mem_type = type; |
| 950 | #endif | 969 | #endif |
| 951 | 970 | ||
| 952 | val = lmalloc (nbytes); | 971 | val = lmalloc (nbytes, clearit); |
| 953 | 972 | ||
| 954 | #if ! USE_LSB_TAG | 973 | #if ! USE_LSB_TAG |
| 955 | /* If the memory just allocated cannot be addressed thru a Lisp | 974 | /* If the memory just allocated cannot be addressed thru a Lisp |
| @@ -1290,16 +1309,21 @@ laligned (void *p, size_t size) | |||
| 1290 | that's never really exercised) for little benefit. */ | 1309 | that's never really exercised) for little benefit. */ |
| 1291 | 1310 | ||
| 1292 | static void * | 1311 | static void * |
| 1293 | lmalloc (size_t size) | 1312 | lmalloc (size_t size, bool clearit) |
| 1294 | { | 1313 | { |
| 1295 | #ifdef USE_ALIGNED_ALLOC | 1314 | #ifdef USE_ALIGNED_ALLOC |
| 1296 | if (! MALLOC_IS_LISP_ALIGNED && size % LISP_ALIGNMENT == 0) | 1315 | if (! MALLOC_IS_LISP_ALIGNED && size % LISP_ALIGNMENT == 0) |
| 1297 | return aligned_alloc (LISP_ALIGNMENT, size); | 1316 | { |
| 1317 | void *p = aligned_alloc (LISP_ALIGNMENT, size); | ||
| 1318 | if (clearit && p) | ||
| 1319 | memclear (p, size); | ||
| 1320 | return p; | ||
| 1321 | } | ||
| 1298 | #endif | 1322 | #endif |
| 1299 | 1323 | ||
| 1300 | while (true) | 1324 | while (true) |
| 1301 | { | 1325 | { |
| 1302 | void *p = malloc (size); | 1326 | void *p = clearit ? calloc (1, size) : malloc (size); |
| 1303 | if (laligned (p, size)) | 1327 | if (laligned (p, size)) |
| 1304 | return p; | 1328 | return p; |
| 1305 | free (p); | 1329 | free (p); |
| @@ -1328,11 +1352,11 @@ lrealloc (void *p, size_t size) | |||
| 1328 | Interval Allocation | 1352 | Interval Allocation |
| 1329 | ***********************************************************************/ | 1353 | ***********************************************************************/ |
| 1330 | 1354 | ||
| 1331 | /* Number of intervals allocated in an interval_block structure. | 1355 | /* Number of intervals allocated in an interval_block structure. */ |
| 1332 | The 1020 is 1024 minus malloc overhead. */ | ||
| 1333 | 1356 | ||
| 1334 | #define INTERVAL_BLOCK_SIZE \ | 1357 | enum { INTERVAL_BLOCK_SIZE |
| 1335 | ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval)) | 1358 | = ((MALLOC_SIZE_NEAR (1024) - sizeof (struct interval_block *)) |
| 1359 | / sizeof (struct interval)) }; | ||
| 1336 | 1360 | ||
| 1337 | /* Intervals are allocated in chunks in the form of an interval_block | 1361 | /* Intervals are allocated in chunks in the form of an interval_block |
| 1338 | structure. */ | 1362 | structure. */ |
| @@ -1377,7 +1401,7 @@ make_interval (void) | |||
| 1377 | if (interval_block_index == INTERVAL_BLOCK_SIZE) | 1401 | if (interval_block_index == INTERVAL_BLOCK_SIZE) |
| 1378 | { | 1402 | { |
| 1379 | struct interval_block *newi | 1403 | struct interval_block *newi |
| 1380 | = lisp_malloc (sizeof *newi, MEM_TYPE_NON_LISP); | 1404 | = lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP); |
| 1381 | 1405 | ||
| 1382 | newi->next = interval_block; | 1406 | newi->next = interval_block; |
| 1383 | interval_block = newi; | 1407 | interval_block = newi; |
| @@ -1444,10 +1468,9 @@ mark_interval_tree (INTERVAL i) | |||
| 1444 | longer used, can be easily recognized, and it's easy to compact the | 1468 | longer used, can be easily recognized, and it's easy to compact the |
| 1445 | sblocks of small strings which we do in compact_small_strings. */ | 1469 | sblocks of small strings which we do in compact_small_strings. */ |
| 1446 | 1470 | ||
| 1447 | /* Size in bytes of an sblock structure used for small strings. This | 1471 | /* Size in bytes of an sblock structure used for small strings. */ |
| 1448 | is 8192 minus malloc overhead. */ | ||
| 1449 | 1472 | ||
| 1450 | #define SBLOCK_SIZE 8188 | 1473 | enum { SBLOCK_SIZE = MALLOC_SIZE_NEAR (8192) }; |
| 1451 | 1474 | ||
| 1452 | /* Strings larger than this are considered large strings. String data | 1475 | /* Strings larger than this are considered large strings. String data |
| 1453 | for large strings is allocated from individual sblocks. */ | 1476 | for large strings is allocated from individual sblocks. */ |
| @@ -1522,11 +1545,11 @@ struct sblock | |||
| 1522 | sdata data[FLEXIBLE_ARRAY_MEMBER]; | 1545 | sdata data[FLEXIBLE_ARRAY_MEMBER]; |
| 1523 | }; | 1546 | }; |
| 1524 | 1547 | ||
| 1525 | /* Number of Lisp strings in a string_block structure. The 1020 is | 1548 | /* Number of Lisp strings in a string_block structure. */ |
| 1526 | 1024 minus malloc overhead. */ | ||
| 1527 | 1549 | ||
| 1528 | #define STRING_BLOCK_SIZE \ | 1550 | enum { STRING_BLOCK_SIZE |
| 1529 | ((1020 - sizeof (struct string_block *)) / sizeof (struct Lisp_String)) | 1551 | = ((MALLOC_SIZE_NEAR (1024) - sizeof (struct string_block *)) |
| 1552 | / sizeof (struct Lisp_String)) }; | ||
| 1530 | 1553 | ||
| 1531 | /* Structure describing a block from which Lisp_String structures | 1554 | /* Structure describing a block from which Lisp_String structures |
| 1532 | are allocated. */ | 1555 | are allocated. */ |
| @@ -1730,7 +1753,7 @@ allocate_string (void) | |||
| 1730 | add all the Lisp_Strings in it to the free-list. */ | 1753 | add all the Lisp_Strings in it to the free-list. */ |
| 1731 | if (string_free_list == NULL) | 1754 | if (string_free_list == NULL) |
| 1732 | { | 1755 | { |
| 1733 | struct string_block *b = lisp_malloc (sizeof *b, MEM_TYPE_STRING); | 1756 | struct string_block *b = lisp_malloc (sizeof *b, false, MEM_TYPE_STRING); |
| 1734 | int i; | 1757 | int i; |
| 1735 | 1758 | ||
| 1736 | b->next = string_blocks; | 1759 | b->next = string_blocks; |
| @@ -1778,15 +1801,16 @@ allocate_string (void) | |||
| 1778 | plus a NUL byte at the end. Allocate an sdata structure DATA for | 1801 | plus a NUL byte at the end. Allocate an sdata structure DATA for |
| 1779 | S, and set S->u.s.data to SDATA->u.data. Store a NUL byte at the | 1802 | S, and set S->u.s.data to SDATA->u.data. Store a NUL byte at the |
| 1780 | end of S->u.s.data. Set S->u.s.size to NCHARS and S->u.s.size_byte | 1803 | end of S->u.s.data. Set S->u.s.size to NCHARS and S->u.s.size_byte |
| 1781 | to NBYTES. Free S->u.s.data if it was initially non-null. */ | 1804 | to NBYTES. Free S->u.s.data if it was initially non-null. |
| 1782 | 1805 | ||
| 1783 | void | 1806 | If CLEARIT, also clear the other bytes of S->u.s.data. */ |
| 1807 | |||
| 1808 | static void | ||
| 1784 | allocate_string_data (struct Lisp_String *s, | 1809 | allocate_string_data (struct Lisp_String *s, |
| 1785 | EMACS_INT nchars, EMACS_INT nbytes) | 1810 | EMACS_INT nchars, EMACS_INT nbytes, bool clearit) |
| 1786 | { | 1811 | { |
| 1787 | sdata *data, *old_data; | 1812 | sdata *data; |
| 1788 | struct sblock *b; | 1813 | struct sblock *b; |
| 1789 | ptrdiff_t old_nbytes; | ||
| 1790 | 1814 | ||
| 1791 | if (STRING_BYTES_MAX < nbytes) | 1815 | if (STRING_BYTES_MAX < nbytes) |
| 1792 | string_overflow (); | 1816 | string_overflow (); |
| @@ -1794,13 +1818,6 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1794 | /* Determine the number of bytes needed to store NBYTES bytes | 1818 | /* Determine the number of bytes needed to store NBYTES bytes |
| 1795 | of string data. */ | 1819 | of string data. */ |
| 1796 | ptrdiff_t needed = sdata_size (nbytes); | 1820 | ptrdiff_t needed = sdata_size (nbytes); |
| 1797 | if (s->u.s.data) | ||
| 1798 | { | ||
| 1799 | old_data = SDATA_OF_STRING (s); | ||
| 1800 | old_nbytes = STRING_BYTES (s); | ||
| 1801 | } | ||
| 1802 | else | ||
| 1803 | old_data = NULL; | ||
| 1804 | 1821 | ||
| 1805 | MALLOC_BLOCK_INPUT; | 1822 | MALLOC_BLOCK_INPUT; |
| 1806 | 1823 | ||
| @@ -1813,7 +1830,7 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1813 | mallopt (M_MMAP_MAX, 0); | 1830 | mallopt (M_MMAP_MAX, 0); |
| 1814 | #endif | 1831 | #endif |
| 1815 | 1832 | ||
| 1816 | b = lisp_malloc (size + GC_STRING_EXTRA, MEM_TYPE_NON_LISP); | 1833 | b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP); |
| 1817 | 1834 | ||
| 1818 | #ifdef DOUG_LEA_MALLOC | 1835 | #ifdef DOUG_LEA_MALLOC |
| 1819 | if (!mmap_lisp_allowed_p ()) | 1836 | if (!mmap_lisp_allowed_p ()) |
| @@ -1825,27 +1842,30 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1825 | b->next_free = data; | 1842 | b->next_free = data; |
| 1826 | large_sblocks = b; | 1843 | large_sblocks = b; |
| 1827 | } | 1844 | } |
| 1828 | else if (current_sblock == NULL | ||
| 1829 | || (((char *) current_sblock + SBLOCK_SIZE | ||
| 1830 | - (char *) current_sblock->next_free) | ||
| 1831 | < (needed + GC_STRING_EXTRA))) | ||
| 1832 | { | ||
| 1833 | /* Not enough room in the current sblock. */ | ||
| 1834 | b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); | ||
| 1835 | data = b->data; | ||
| 1836 | b->next = NULL; | ||
| 1837 | b->next_free = data; | ||
| 1838 | |||
| 1839 | if (current_sblock) | ||
| 1840 | current_sblock->next = b; | ||
| 1841 | else | ||
| 1842 | oldest_sblock = b; | ||
| 1843 | current_sblock = b; | ||
| 1844 | } | ||
| 1845 | else | 1845 | else |
| 1846 | { | 1846 | { |
| 1847 | b = current_sblock; | 1847 | b = current_sblock; |
| 1848 | |||
| 1849 | if (b == NULL | ||
| 1850 | || (SBLOCK_SIZE - GC_STRING_EXTRA | ||
| 1851 | < (char *) b->next_free - (char *) b + needed)) | ||
| 1852 | { | ||
| 1853 | /* Not enough room in the current sblock. */ | ||
| 1854 | b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP); | ||
| 1855 | data = b->data; | ||
| 1856 | b->next = NULL; | ||
| 1857 | b->next_free = data; | ||
| 1858 | |||
| 1859 | if (current_sblock) | ||
| 1860 | current_sblock->next = b; | ||
| 1861 | else | ||
| 1862 | oldest_sblock = b; | ||
| 1863 | current_sblock = b; | ||
| 1864 | } | ||
| 1865 | |||
| 1848 | data = b->next_free; | 1866 | data = b->next_free; |
| 1867 | if (clearit) | ||
| 1868 | memset (SDATA_DATA (data), 0, nbytes); | ||
| 1849 | } | 1869 | } |
| 1850 | 1870 | ||
| 1851 | data->string = s; | 1871 | data->string = s; |
| @@ -1866,16 +1886,55 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1866 | GC_STRING_OVERRUN_COOKIE_SIZE); | 1886 | GC_STRING_OVERRUN_COOKIE_SIZE); |
| 1867 | #endif | 1887 | #endif |
| 1868 | 1888 | ||
| 1869 | /* Note that Faset may call to this function when S has already data | 1889 | tally_consing (needed); |
| 1870 | assigned. In this case, mark data as free by setting it's string | 1890 | } |
| 1871 | back-pointer to null, and record the size of the data in it. */ | 1891 | |
| 1872 | if (old_data) | 1892 | /* Reallocate multibyte STRING data when a single character is replaced. |
| 1893 | The character is at byte offset CIDX_BYTE in the string. | ||
| 1894 | The character being replaced is CLEN bytes long, | ||
| 1895 | and the character that will replace it is NEW_CLEN bytes long. | ||
| 1896 | Return the address of where the caller should store the | ||
| 1897 | the new character. */ | ||
| 1898 | |||
| 1899 | unsigned char * | ||
| 1900 | resize_string_data (Lisp_Object string, ptrdiff_t cidx_byte, | ||
| 1901 | int clen, int new_clen) | ||
| 1902 | { | ||
| 1903 | eassume (STRING_MULTIBYTE (string)); | ||
| 1904 | sdata *old_sdata = SDATA_OF_STRING (XSTRING (string)); | ||
| 1905 | ptrdiff_t nchars = SCHARS (string); | ||
| 1906 | ptrdiff_t nbytes = SBYTES (string); | ||
| 1907 | ptrdiff_t new_nbytes = nbytes + (new_clen - clen); | ||
| 1908 | unsigned char *data = SDATA (string); | ||
| 1909 | unsigned char *new_charaddr; | ||
| 1910 | |||
| 1911 | if (sdata_size (nbytes) == sdata_size (new_nbytes)) | ||
| 1873 | { | 1912 | { |
| 1874 | SDATA_NBYTES (old_data) = old_nbytes; | 1913 | /* No need to reallocate, as the size change falls within the |
| 1875 | old_data->string = NULL; | 1914 | alignment slop. */ |
| 1915 | XSTRING (string)->u.s.size_byte = new_nbytes; | ||
| 1916 | new_charaddr = data + cidx_byte; | ||
| 1917 | memmove (new_charaddr + new_clen, new_charaddr + clen, | ||
| 1918 | nbytes - (cidx_byte + (clen - 1))); | ||
| 1919 | } | ||
| 1920 | else | ||
| 1921 | { | ||
| 1922 | allocate_string_data (XSTRING (string), nchars, new_nbytes, false); | ||
| 1923 | unsigned char *new_data = SDATA (string); | ||
| 1924 | new_charaddr = new_data + cidx_byte; | ||
| 1925 | memcpy (new_charaddr + new_clen, data + cidx_byte + clen, | ||
| 1926 | nbytes - (cidx_byte + clen)); | ||
| 1927 | memcpy (new_data, data, cidx_byte); | ||
| 1928 | |||
| 1929 | /* Mark old string data as free by setting its string back-pointer | ||
| 1930 | to null, and record the size of the data in it. */ | ||
| 1931 | SDATA_NBYTES (old_sdata) = nbytes; | ||
| 1932 | old_sdata->string = NULL; | ||
| 1876 | } | 1933 | } |
| 1877 | 1934 | ||
| 1878 | tally_consing (needed); | 1935 | clear_string_char_byte_cache (); |
| 1936 | |||
| 1937 | return new_charaddr; | ||
| 1879 | } | 1938 | } |
| 1880 | 1939 | ||
| 1881 | 1940 | ||
| @@ -2110,6 +2169,9 @@ string_overflow (void) | |||
| 2110 | error ("Maximum string size exceeded"); | 2169 | error ("Maximum string size exceeded"); |
| 2111 | } | 2170 | } |
| 2112 | 2171 | ||
| 2172 | static Lisp_Object make_clear_string (EMACS_INT, bool); | ||
| 2173 | static Lisp_Object make_clear_multibyte_string (EMACS_INT, EMACS_INT, bool); | ||
| 2174 | |||
| 2113 | DEFUN ("make-string", Fmake_string, Smake_string, 2, 3, 0, | 2175 | DEFUN ("make-string", Fmake_string, Smake_string, 2, 3, 0, |
| 2114 | doc: /* Return a newly created string of length LENGTH, with INIT in each element. | 2176 | doc: /* Return a newly created string of length LENGTH, with INIT in each element. |
| 2115 | LENGTH must be an integer. | 2177 | LENGTH must be an integer. |
| @@ -2118,19 +2180,20 @@ If optional argument MULTIBYTE is non-nil, the result will be | |||
| 2118 | a multibyte string even if INIT is an ASCII character. */) | 2180 | a multibyte string even if INIT is an ASCII character. */) |
| 2119 | (Lisp_Object length, Lisp_Object init, Lisp_Object multibyte) | 2181 | (Lisp_Object length, Lisp_Object init, Lisp_Object multibyte) |
| 2120 | { | 2182 | { |
| 2121 | register Lisp_Object val; | 2183 | Lisp_Object val; |
| 2122 | int c; | ||
| 2123 | EMACS_INT nbytes; | 2184 | EMACS_INT nbytes; |
| 2124 | 2185 | ||
| 2125 | CHECK_FIXNAT (length); | 2186 | CHECK_FIXNAT (length); |
| 2126 | CHECK_CHARACTER (init); | 2187 | CHECK_CHARACTER (init); |
| 2127 | 2188 | ||
| 2128 | c = XFIXNAT (init); | 2189 | int c = XFIXNAT (init); |
| 2190 | bool clearit = !c; | ||
| 2191 | |||
| 2129 | if (ASCII_CHAR_P (c) && NILP (multibyte)) | 2192 | if (ASCII_CHAR_P (c) && NILP (multibyte)) |
| 2130 | { | 2193 | { |
| 2131 | nbytes = XFIXNUM (length); | 2194 | nbytes = XFIXNUM (length); |
| 2132 | val = make_uninit_string (nbytes); | 2195 | val = make_clear_string (nbytes, clearit); |
| 2133 | if (nbytes) | 2196 | if (nbytes && !clearit) |
| 2134 | { | 2197 | { |
| 2135 | memset (SDATA (val), c, nbytes); | 2198 | memset (SDATA (val), c, nbytes); |
| 2136 | SDATA (val)[nbytes] = 0; | 2199 | SDATA (val)[nbytes] = 0; |
| @@ -2141,26 +2204,27 @@ a multibyte string even if INIT is an ASCII character. */) | |||
| 2141 | unsigned char str[MAX_MULTIBYTE_LENGTH]; | 2204 | unsigned char str[MAX_MULTIBYTE_LENGTH]; |
| 2142 | ptrdiff_t len = CHAR_STRING (c, str); | 2205 | ptrdiff_t len = CHAR_STRING (c, str); |
| 2143 | EMACS_INT string_len = XFIXNUM (length); | 2206 | EMACS_INT string_len = XFIXNUM (length); |
| 2144 | unsigned char *p, *beg, *end; | ||
| 2145 | 2207 | ||
| 2146 | if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes)) | 2208 | if (INT_MULTIPLY_WRAPV (len, string_len, &nbytes)) |
| 2147 | string_overflow (); | 2209 | string_overflow (); |
| 2148 | val = make_uninit_multibyte_string (string_len, nbytes); | 2210 | val = make_clear_multibyte_string (string_len, nbytes, clearit); |
| 2149 | for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len) | 2211 | if (!clearit) |
| 2150 | { | 2212 | { |
| 2151 | /* First time we just copy `str' to the data of `val'. */ | 2213 | unsigned char *beg = SDATA (val), *end = beg + nbytes; |
| 2152 | if (p == beg) | 2214 | for (unsigned char *p = beg; p < end; p += len) |
| 2153 | memcpy (p, str, len); | ||
| 2154 | else | ||
| 2155 | { | 2215 | { |
| 2156 | /* Next time we copy largest possible chunk from | 2216 | /* First time we just copy STR to the data of VAL. */ |
| 2157 | initialized to uninitialized part of `val'. */ | 2217 | if (p == beg) |
| 2158 | len = min (p - beg, end - p); | 2218 | memcpy (p, str, len); |
| 2159 | memcpy (p, beg, len); | 2219 | else |
| 2220 | { | ||
| 2221 | /* Next time we copy largest possible chunk from | ||
| 2222 | initialized to uninitialized part of VAL. */ | ||
| 2223 | len = min (p - beg, end - p); | ||
| 2224 | memcpy (p, beg, len); | ||
| 2225 | } | ||
| 2160 | } | 2226 | } |
| 2161 | } | 2227 | } |
| 2162 | if (nbytes) | ||
| 2163 | *p = 0; | ||
| 2164 | } | 2228 | } |
| 2165 | 2229 | ||
| 2166 | return val; | 2230 | return val; |
| @@ -2330,26 +2394,37 @@ make_specified_string (const char *contents, | |||
| 2330 | 2394 | ||
| 2331 | 2395 | ||
| 2332 | /* Return a unibyte Lisp_String set up to hold LENGTH characters | 2396 | /* Return a unibyte Lisp_String set up to hold LENGTH characters |
| 2333 | occupying LENGTH bytes. */ | 2397 | occupying LENGTH bytes. If CLEARIT, clear its contents to null |
| 2398 | bytes; otherwise, the contents are uninitialized. */ | ||
| 2334 | 2399 | ||
| 2335 | Lisp_Object | 2400 | static Lisp_Object |
| 2336 | make_uninit_string (EMACS_INT length) | 2401 | make_clear_string (EMACS_INT length, bool clearit) |
| 2337 | { | 2402 | { |
| 2338 | Lisp_Object val; | 2403 | Lisp_Object val; |
| 2339 | 2404 | ||
| 2340 | if (!length) | 2405 | if (!length) |
| 2341 | return empty_unibyte_string; | 2406 | return empty_unibyte_string; |
| 2342 | val = make_uninit_multibyte_string (length, length); | 2407 | val = make_clear_multibyte_string (length, length, clearit); |
| 2343 | STRING_SET_UNIBYTE (val); | 2408 | STRING_SET_UNIBYTE (val); |
| 2344 | return val; | 2409 | return val; |
| 2345 | } | 2410 | } |
| 2346 | 2411 | ||
| 2412 | /* Return a unibyte Lisp_String set up to hold LENGTH characters | ||
| 2413 | occupying LENGTH bytes. */ | ||
| 2414 | |||
| 2415 | Lisp_Object | ||
| 2416 | make_uninit_string (EMACS_INT length) | ||
| 2417 | { | ||
| 2418 | return make_clear_string (length, false); | ||
| 2419 | } | ||
| 2420 | |||
| 2347 | 2421 | ||
| 2348 | /* Return a multibyte Lisp_String set up to hold NCHARS characters | 2422 | /* Return a multibyte Lisp_String set up to hold NCHARS characters |
| 2349 | which occupy NBYTES bytes. */ | 2423 | which occupy NBYTES bytes. If CLEARIT, clear its contents to null |
| 2424 | bytes; otherwise, the contents are uninitialized. */ | ||
| 2350 | 2425 | ||
| 2351 | Lisp_Object | 2426 | static Lisp_Object |
| 2352 | make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | 2427 | make_clear_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes, bool clearit) |
| 2353 | { | 2428 | { |
| 2354 | Lisp_Object string; | 2429 | Lisp_Object string; |
| 2355 | struct Lisp_String *s; | 2430 | struct Lisp_String *s; |
| @@ -2361,12 +2436,21 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | |||
| 2361 | 2436 | ||
| 2362 | s = allocate_string (); | 2437 | s = allocate_string (); |
| 2363 | s->u.s.intervals = NULL; | 2438 | s->u.s.intervals = NULL; |
| 2364 | allocate_string_data (s, nchars, nbytes); | 2439 | allocate_string_data (s, nchars, nbytes, clearit); |
| 2365 | XSETSTRING (string, s); | 2440 | XSETSTRING (string, s); |
| 2366 | string_chars_consed += nbytes; | 2441 | string_chars_consed += nbytes; |
| 2367 | return string; | 2442 | return string; |
| 2368 | } | 2443 | } |
| 2369 | 2444 | ||
| 2445 | /* Return a multibyte Lisp_String set up to hold NCHARS characters | ||
| 2446 | which occupy NBYTES bytes. */ | ||
| 2447 | |||
| 2448 | Lisp_Object | ||
| 2449 | make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | ||
| 2450 | { | ||
| 2451 | return make_clear_multibyte_string (nchars, nbytes, false); | ||
| 2452 | } | ||
| 2453 | |||
| 2370 | /* Print arguments to BUF according to a FORMAT, then return | 2454 | /* Print arguments to BUF according to a FORMAT, then return |
| 2371 | a Lisp_String initialized with the data from BUF. */ | 2455 | a Lisp_String initialized with the data from BUF. */ |
| 2372 | 2456 | ||
| @@ -3023,6 +3107,14 @@ cleanup_vector (struct Lisp_Vector *vector) | |||
| 3023 | if (uptr->finalizer) | 3107 | if (uptr->finalizer) |
| 3024 | uptr->finalizer (uptr->p); | 3108 | uptr->finalizer (uptr->p); |
| 3025 | } | 3109 | } |
| 3110 | #ifdef HAVE_MODULES | ||
| 3111 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MODULE_FUNCTION)) | ||
| 3112 | { | ||
| 3113 | ATTRIBUTE_MAY_ALIAS struct Lisp_Module_Function *function | ||
| 3114 | = (struct Lisp_Module_Function *) vector; | ||
| 3115 | module_finalize_function (function); | ||
| 3116 | } | ||
| 3117 | #endif | ||
| 3026 | } | 3118 | } |
| 3027 | 3119 | ||
| 3028 | /* Reclaim space used by unmarked vectors. */ | 3120 | /* Reclaim space used by unmarked vectors. */ |
| @@ -3137,7 +3229,7 @@ sweep_vectors (void) | |||
| 3137 | at most VECTOR_ELTS_MAX. */ | 3229 | at most VECTOR_ELTS_MAX. */ |
| 3138 | 3230 | ||
| 3139 | static struct Lisp_Vector * | 3231 | static struct Lisp_Vector * |
| 3140 | allocate_vectorlike (ptrdiff_t len) | 3232 | allocate_vectorlike (ptrdiff_t len, bool clearit) |
| 3141 | { | 3233 | { |
| 3142 | eassert (0 < len && len <= VECTOR_ELTS_MAX); | 3234 | eassert (0 < len && len <= VECTOR_ELTS_MAX); |
| 3143 | ptrdiff_t nbytes = header_size + len * word_size; | 3235 | ptrdiff_t nbytes = header_size + len * word_size; |
| @@ -3151,11 +3243,15 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 3151 | #endif | 3243 | #endif |
| 3152 | 3244 | ||
| 3153 | if (nbytes <= VBLOCK_BYTES_MAX) | 3245 | if (nbytes <= VBLOCK_BYTES_MAX) |
| 3154 | p = allocate_vector_from_block (vroundup (nbytes)); | 3246 | { |
| 3247 | p = allocate_vector_from_block (vroundup (nbytes)); | ||
| 3248 | if (clearit) | ||
| 3249 | memclear (p, nbytes); | ||
| 3250 | } | ||
| 3155 | else | 3251 | else |
| 3156 | { | 3252 | { |
| 3157 | struct large_vector *lv = lisp_malloc (large_vector_offset + nbytes, | 3253 | struct large_vector *lv = lisp_malloc (large_vector_offset + nbytes, |
| 3158 | MEM_TYPE_VECTORLIKE); | 3254 | clearit, MEM_TYPE_VECTORLIKE); |
| 3159 | lv->next = large_vectors; | 3255 | lv->next = large_vectors; |
| 3160 | large_vectors = lv; | 3256 | large_vectors = lv; |
| 3161 | p = large_vector_vec (lv); | 3257 | p = large_vector_vec (lv); |
| @@ -3178,20 +3274,37 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 3178 | } | 3274 | } |
| 3179 | 3275 | ||
| 3180 | 3276 | ||
| 3181 | /* Allocate a vector with LEN slots. */ | 3277 | /* Allocate a vector with LEN slots. If CLEARIT, clear its slots; |
| 3278 | otherwise the vector's slots are uninitialized. */ | ||
| 3182 | 3279 | ||
| 3183 | struct Lisp_Vector * | 3280 | static struct Lisp_Vector * |
| 3184 | allocate_vector (ptrdiff_t len) | 3281 | allocate_clear_vector (ptrdiff_t len, bool clearit) |
| 3185 | { | 3282 | { |
| 3186 | if (len == 0) | 3283 | if (len == 0) |
| 3187 | return XVECTOR (zero_vector); | 3284 | return XVECTOR (zero_vector); |
| 3188 | if (VECTOR_ELTS_MAX < len) | 3285 | if (VECTOR_ELTS_MAX < len) |
| 3189 | memory_full (SIZE_MAX); | 3286 | memory_full (SIZE_MAX); |
| 3190 | struct Lisp_Vector *v = allocate_vectorlike (len); | 3287 | struct Lisp_Vector *v = allocate_vectorlike (len, clearit); |
| 3191 | v->header.size = len; | 3288 | v->header.size = len; |
| 3192 | return v; | 3289 | return v; |
| 3193 | } | 3290 | } |
| 3194 | 3291 | ||
| 3292 | /* Allocate a vector with LEN uninitialized slots. */ | ||
| 3293 | |||
| 3294 | struct Lisp_Vector * | ||
| 3295 | allocate_vector (ptrdiff_t len) | ||
| 3296 | { | ||
| 3297 | return allocate_clear_vector (len, false); | ||
| 3298 | } | ||
| 3299 | |||
| 3300 | /* Allocate a vector with LEN nil slots. */ | ||
| 3301 | |||
| 3302 | struct Lisp_Vector * | ||
| 3303 | allocate_nil_vector (ptrdiff_t len) | ||
| 3304 | { | ||
| 3305 | return allocate_clear_vector (len, true); | ||
| 3306 | } | ||
| 3307 | |||
| 3195 | 3308 | ||
| 3196 | /* Allocate other vector-like structures. */ | 3309 | /* Allocate other vector-like structures. */ |
| 3197 | 3310 | ||
| @@ -3208,7 +3321,7 @@ allocate_pseudovector (int memlen, int lisplen, | |||
| 3208 | eassert (lisplen <= size_max); | 3321 | eassert (lisplen <= size_max); |
| 3209 | eassert (memlen <= size_max + rest_max); | 3322 | eassert (memlen <= size_max + rest_max); |
| 3210 | 3323 | ||
| 3211 | struct Lisp_Vector *v = allocate_vectorlike (memlen); | 3324 | struct Lisp_Vector *v = allocate_vectorlike (memlen, false); |
| 3212 | /* Only the first LISPLEN slots will be traced normally by the GC. */ | 3325 | /* Only the first LISPLEN slots will be traced normally by the GC. */ |
| 3213 | memclear (v->contents, zerolen * word_size); | 3326 | memclear (v->contents, zerolen * word_size); |
| 3214 | XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen); | 3327 | XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen); |
| @@ -3218,7 +3331,7 @@ allocate_pseudovector (int memlen, int lisplen, | |||
| 3218 | struct buffer * | 3331 | struct buffer * |
| 3219 | allocate_buffer (void) | 3332 | allocate_buffer (void) |
| 3220 | { | 3333 | { |
| 3221 | struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER); | 3334 | struct buffer *b = lisp_malloc (sizeof *b, false, MEM_TYPE_BUFFER); |
| 3222 | 3335 | ||
| 3223 | BUFFER_PVEC_INIT (b); | 3336 | BUFFER_PVEC_INIT (b); |
| 3224 | /* Put B on the chain of all buffers including killed ones. */ | 3337 | /* Put B on the chain of all buffers including killed ones. */ |
| @@ -3238,7 +3351,7 @@ allocate_record (EMACS_INT count) | |||
| 3238 | if (count > PSEUDOVECTOR_SIZE_MASK) | 3351 | if (count > PSEUDOVECTOR_SIZE_MASK) |
| 3239 | error ("Attempt to allocate a record of %"pI"d slots; max is %d", | 3352 | error ("Attempt to allocate a record of %"pI"d slots; max is %d", |
| 3240 | count, PSEUDOVECTOR_SIZE_MASK); | 3353 | count, PSEUDOVECTOR_SIZE_MASK); |
| 3241 | struct Lisp_Vector *p = allocate_vectorlike (count); | 3354 | struct Lisp_Vector *p = allocate_vectorlike (count, false); |
| 3242 | p->header.size = count; | 3355 | p->header.size = count; |
| 3243 | XSETPVECTYPE (p, PVEC_RECORD); | 3356 | XSETPVECTYPE (p, PVEC_RECORD); |
| 3244 | return p; | 3357 | return p; |
| @@ -3291,9 +3404,11 @@ See also the function `vector'. */) | |||
| 3291 | Lisp_Object | 3404 | Lisp_Object |
| 3292 | make_vector (ptrdiff_t length, Lisp_Object init) | 3405 | make_vector (ptrdiff_t length, Lisp_Object init) |
| 3293 | { | 3406 | { |
| 3294 | struct Lisp_Vector *p = allocate_vector (length); | 3407 | bool clearit = NIL_IS_ZERO && NILP (init); |
| 3295 | for (ptrdiff_t i = 0; i < length; i++) | 3408 | struct Lisp_Vector *p = allocate_clear_vector (length, clearit); |
| 3296 | p->contents[i] = init; | 3409 | if (!clearit) |
| 3410 | for (ptrdiff_t i = 0; i < length; i++) | ||
| 3411 | p->contents[i] = init; | ||
| 3297 | return make_lisp_ptr (p, Lisp_Vectorlike); | 3412 | return make_lisp_ptr (p, Lisp_Vectorlike); |
| 3298 | } | 3413 | } |
| 3299 | 3414 | ||
| @@ -3442,7 +3557,7 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3442 | if (symbol_block_index == SYMBOL_BLOCK_SIZE) | 3557 | if (symbol_block_index == SYMBOL_BLOCK_SIZE) |
| 3443 | { | 3558 | { |
| 3444 | struct symbol_block *new | 3559 | struct symbol_block *new |
| 3445 | = lisp_malloc (sizeof *new, MEM_TYPE_SYMBOL); | 3560 | = lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL); |
| 3446 | new->next = symbol_block; | 3561 | new->next = symbol_block; |
| 3447 | symbol_block = new; | 3562 | symbol_block = new; |
| 3448 | symbol_block_index = 0; | 3563 | symbol_block_index = 0; |
| @@ -3904,10 +4019,10 @@ refill_memory_reserve (void) | |||
| 3904 | MEM_TYPE_SPARE); | 4019 | MEM_TYPE_SPARE); |
| 3905 | if (spare_memory[5] == 0) | 4020 | if (spare_memory[5] == 0) |
| 3906 | spare_memory[5] = lisp_malloc (sizeof (struct string_block), | 4021 | spare_memory[5] = lisp_malloc (sizeof (struct string_block), |
| 3907 | MEM_TYPE_SPARE); | 4022 | false, MEM_TYPE_SPARE); |
| 3908 | if (spare_memory[6] == 0) | 4023 | if (spare_memory[6] == 0) |
| 3909 | spare_memory[6] = lisp_malloc (sizeof (struct string_block), | 4024 | spare_memory[6] = lisp_malloc (sizeof (struct string_block), |
| 3910 | MEM_TYPE_SPARE); | 4025 | false, MEM_TYPE_SPARE); |
| 3911 | if (spare_memory[0] && spare_memory[1] && spare_memory[5]) | 4026 | if (spare_memory[0] && spare_memory[1] && spare_memory[5]) |
| 3912 | Vmemory_full = Qnil; | 4027 | Vmemory_full = Qnil; |
| 3913 | #endif | 4028 | #endif |