diff options
| author | Eli Zaretskii | 2013-11-18 18:45:48 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2013-11-18 18:45:48 +0200 |
| commit | 18b35e2c7a3ff95fb4a07e58c3f57c70c65c0701 (patch) | |
| tree | 7a837a755a7c22d3258408cb384d01479ad88232 /src/alloc.c | |
| parent | df87c56cdf6c8c13e8760bdc409e2eb0fda55b0b (diff) | |
| parent | 37c790b38599cc80a16c6a76152abbf8160fe2a1 (diff) | |
| download | emacs-18b35e2c7a3ff95fb4a07e58c3f57c70c65c0701.tar.gz emacs-18b35e2c7a3ff95fb4a07e58c3f57c70c65c0701.zip | |
Merge from mainline.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 559 |
1 files changed, 337 insertions, 222 deletions
diff --git a/src/alloc.c b/src/alloc.c index 02deaa94af1..f12fdc5c861 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -361,13 +361,21 @@ static int staticidx; | |||
| 361 | 361 | ||
| 362 | static void *pure_alloc (size_t, int); | 362 | static void *pure_alloc (size_t, int); |
| 363 | 363 | ||
| 364 | /* Return X rounded to the next multiple of Y. Arguments should not | ||
| 365 | have side effects, as they are evaluated more than once. Assume X | ||
| 366 | + Y - 1 does not overflow. Tune for Y being a power of 2. */ | ||
| 364 | 367 | ||
| 365 | /* Value is SZ rounded up to the next multiple of ALIGNMENT. | 368 | #define ROUNDUP(x, y) ((y) & ((y) - 1) \ |
| 366 | ALIGNMENT must be a power of 2. */ | 369 | ? ((x) + (y) - 1) - ((x) + (y) - 1) % (y) \ |
| 370 | : ((x) + (y) - 1) & ~ ((y) - 1)) | ||
| 367 | 371 | ||
| 368 | #define ALIGN(ptr, ALIGNMENT) \ | 372 | /* Return PTR rounded up to the next multiple of ALIGNMENT. */ |
| 369 | ((void *) (((uintptr_t) (ptr) + (ALIGNMENT) - 1) \ | 373 | |
| 370 | & ~ ((ALIGNMENT) - 1))) | 374 | static void * |
| 375 | ALIGN (void *ptr, int alignment) | ||
| 376 | { | ||
| 377 | return (void *) ROUNDUP ((uintptr_t) ptr, alignment); | ||
| 378 | } | ||
| 371 | 379 | ||
| 372 | static void | 380 | static void |
| 373 | XFLOAT_INIT (Lisp_Object f, double n) | 381 | XFLOAT_INIT (Lisp_Object f, double n) |
| @@ -912,8 +920,20 @@ lisp_free (void *block) | |||
| 912 | /* The entry point is lisp_align_malloc which returns blocks of at most | 920 | /* The entry point is lisp_align_malloc which returns blocks of at most |
| 913 | BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ | 921 | BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ |
| 914 | 922 | ||
| 915 | #if defined (HAVE_POSIX_MEMALIGN) && defined (SYSTEM_MALLOC) | 923 | #if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC |
| 916 | #define USE_POSIX_MEMALIGN 1 | 924 | # define USE_ALIGNED_ALLOC 1 |
| 925 | /* Defined in gmalloc.c. */ | ||
| 926 | void *aligned_alloc (size_t, size_t); | ||
| 927 | #elif defined HAVE_ALIGNED_ALLOC | ||
| 928 | # define USE_ALIGNED_ALLOC 1 | ||
| 929 | #elif defined HAVE_POSIX_MEMALIGN | ||
| 930 | # define USE_ALIGNED_ALLOC 1 | ||
| 931 | static void * | ||
| 932 | aligned_alloc (size_t alignment, size_t size) | ||
| 933 | { | ||
| 934 | void *p; | ||
| 935 | return posix_memalign (&p, alignment, size) == 0 ? p : 0; | ||
| 936 | } | ||
| 917 | #endif | 937 | #endif |
| 918 | 938 | ||
| 919 | /* BLOCK_ALIGN has to be a power of 2. */ | 939 | /* BLOCK_ALIGN has to be a power of 2. */ |
| @@ -923,7 +943,7 @@ lisp_free (void *block) | |||
| 923 | malloc a chance to minimize the amount of memory wasted to alignment. | 943 | malloc a chance to minimize the amount of memory wasted to alignment. |
| 924 | It should be tuned to the particular malloc library used. | 944 | It should be tuned to the particular malloc library used. |
| 925 | On glibc-2.3.2, malloc never tries to align, so a padding of 0 is best. | 945 | On glibc-2.3.2, malloc never tries to align, so a padding of 0 is best. |
| 926 | posix_memalign on the other hand would ideally prefer a value of 4 | 946 | aligned_alloc on the other hand would ideally prefer a value of 4 |
| 927 | because otherwise, there's 1020 bytes wasted between each ablocks. | 947 | because otherwise, there's 1020 bytes wasted between each ablocks. |
| 928 | In Emacs, testing shows that those 1020 can most of the time be | 948 | In Emacs, testing shows that those 1020 can most of the time be |
| 929 | efficiently used by malloc to place other objects, so a value of 0 can | 949 | efficiently used by malloc to place other objects, so a value of 0 can |
| @@ -968,7 +988,7 @@ struct ablocks | |||
| 968 | struct ablock blocks[ABLOCKS_SIZE]; | 988 | struct ablock blocks[ABLOCKS_SIZE]; |
| 969 | }; | 989 | }; |
| 970 | 990 | ||
| 971 | /* Size of the block requested from malloc or posix_memalign. */ | 991 | /* Size of the block requested from malloc or aligned_alloc. */ |
| 972 | #define ABLOCKS_BYTES (sizeof (struct ablocks) - BLOCK_PADDING) | 992 | #define ABLOCKS_BYTES (sizeof (struct ablocks) - BLOCK_PADDING) |
| 973 | 993 | ||
| 974 | #define ABLOCK_ABASE(block) \ | 994 | #define ABLOCK_ABASE(block) \ |
| @@ -980,7 +1000,7 @@ struct ablocks | |||
| 980 | #define ABLOCKS_BUSY(abase) ((abase)->blocks[0].abase) | 1000 | #define ABLOCKS_BUSY(abase) ((abase)->blocks[0].abase) |
| 981 | 1001 | ||
| 982 | /* Pointer to the (not necessarily aligned) malloc block. */ | 1002 | /* Pointer to the (not necessarily aligned) malloc block. */ |
| 983 | #ifdef USE_POSIX_MEMALIGN | 1003 | #ifdef USE_ALIGNED_ALLOC |
| 984 | #define ABLOCKS_BASE(abase) (abase) | 1004 | #define ABLOCKS_BASE(abase) (abase) |
| 985 | #else | 1005 | #else |
| 986 | #define ABLOCKS_BASE(abase) \ | 1006 | #define ABLOCKS_BASE(abase) \ |
| @@ -1019,13 +1039,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) | |||
| 1019 | mallopt (M_MMAP_MAX, 0); | 1039 | mallopt (M_MMAP_MAX, 0); |
| 1020 | #endif | 1040 | #endif |
| 1021 | 1041 | ||
| 1022 | #ifdef USE_POSIX_MEMALIGN | 1042 | #ifdef USE_ALIGNED_ALLOC |
| 1023 | { | 1043 | abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES); |
| 1024 | int err = posix_memalign (&base, BLOCK_ALIGN, ABLOCKS_BYTES); | ||
| 1025 | if (err) | ||
| 1026 | base = NULL; | ||
| 1027 | abase = base; | ||
| 1028 | } | ||
| 1029 | #else | 1044 | #else |
| 1030 | base = malloc (ABLOCKS_BYTES); | 1045 | base = malloc (ABLOCKS_BYTES); |
| 1031 | abase = ALIGN (base, BLOCK_ALIGN); | 1046 | abase = ALIGN (base, BLOCK_ALIGN); |
| @@ -1280,28 +1295,32 @@ mark_interval (register INTERVAL i, Lisp_Object dummy) | |||
| 1280 | 1295 | ||
| 1281 | #define LARGE_STRING_BYTES 1024 | 1296 | #define LARGE_STRING_BYTES 1024 |
| 1282 | 1297 | ||
| 1283 | /* Struct or union describing string memory sub-allocated from an sblock. | 1298 | /* The SDATA typedef is a struct or union describing string memory |
| 1284 | This is where the contents of Lisp strings are stored. */ | 1299 | sub-allocated from an sblock. This is where the contents of Lisp |
| 1285 | 1300 | strings are stored. */ | |
| 1286 | #ifdef GC_CHECK_STRING_BYTES | ||
| 1287 | 1301 | ||
| 1288 | typedef struct | 1302 | struct sdata |
| 1289 | { | 1303 | { |
| 1290 | /* Back-pointer to the string this sdata belongs to. If null, this | 1304 | /* Back-pointer to the string this sdata belongs to. If null, this |
| 1291 | structure is free, and the NBYTES member of the union below | 1305 | structure is free, and NBYTES (in this structure or in the union below) |
| 1292 | contains the string's byte size (the same value that STRING_BYTES | 1306 | contains the string's byte size (the same value that STRING_BYTES |
| 1293 | would return if STRING were non-null). If non-null, STRING_BYTES | 1307 | would return if STRING were non-null). If non-null, STRING_BYTES |
| 1294 | (STRING) is the size of the data, and DATA contains the string's | 1308 | (STRING) is the size of the data, and DATA contains the string's |
| 1295 | contents. */ | 1309 | contents. */ |
| 1296 | struct Lisp_String *string; | 1310 | struct Lisp_String *string; |
| 1297 | 1311 | ||
| 1312 | #ifdef GC_CHECK_STRING_BYTES | ||
| 1298 | ptrdiff_t nbytes; | 1313 | ptrdiff_t nbytes; |
| 1314 | #endif | ||
| 1315 | |||
| 1299 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; | 1316 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; |
| 1300 | } sdata; | 1317 | }; |
| 1301 | 1318 | ||
| 1319 | #ifdef GC_CHECK_STRING_BYTES | ||
| 1320 | |||
| 1321 | typedef struct sdata sdata; | ||
| 1302 | #define SDATA_NBYTES(S) (S)->nbytes | 1322 | #define SDATA_NBYTES(S) (S)->nbytes |
| 1303 | #define SDATA_DATA(S) (S)->data | 1323 | #define SDATA_DATA(S) (S)->data |
| 1304 | #define SDATA_SELECTOR(member) member | ||
| 1305 | 1324 | ||
| 1306 | #else | 1325 | #else |
| 1307 | 1326 | ||
| @@ -1309,12 +1328,16 @@ typedef union | |||
| 1309 | { | 1328 | { |
| 1310 | struct Lisp_String *string; | 1329 | struct Lisp_String *string; |
| 1311 | 1330 | ||
| 1312 | /* When STRING is non-null. */ | 1331 | /* When STRING is nonnull, this union is actually of type 'struct sdata', |
| 1313 | struct | 1332 | which has a flexible array member. However, if implemented by |
| 1314 | { | 1333 | giving this union a member of type 'struct sdata', the union |
| 1315 | struct Lisp_String *string; | 1334 | could not be the last (flexible) member of 'struct sblock', |
| 1316 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; | 1335 | because C99 prohibits a flexible array member from having a type |
| 1317 | } u; | 1336 | that is itself a flexible array. So, comment this member out here, |
| 1337 | but remember that the option's there when using this union. */ | ||
| 1338 | #if 0 | ||
| 1339 | struct sdata u; | ||
| 1340 | #endif | ||
| 1318 | 1341 | ||
| 1319 | /* When STRING is null. */ | 1342 | /* When STRING is null. */ |
| 1320 | struct | 1343 | struct |
| @@ -1325,13 +1348,11 @@ typedef union | |||
| 1325 | } sdata; | 1348 | } sdata; |
| 1326 | 1349 | ||
| 1327 | #define SDATA_NBYTES(S) (S)->n.nbytes | 1350 | #define SDATA_NBYTES(S) (S)->n.nbytes |
| 1328 | #define SDATA_DATA(S) (S)->u.data | 1351 | #define SDATA_DATA(S) ((struct sdata *) (S))->data |
| 1329 | #define SDATA_SELECTOR(member) u.member | ||
| 1330 | 1352 | ||
| 1331 | #endif /* not GC_CHECK_STRING_BYTES */ | 1353 | #endif /* not GC_CHECK_STRING_BYTES */ |
| 1332 | 1354 | ||
| 1333 | #define SDATA_DATA_OFFSET offsetof (sdata, SDATA_SELECTOR (data)) | 1355 | enum { SDATA_DATA_OFFSET = offsetof (struct sdata, data) }; |
| 1334 | |||
| 1335 | 1356 | ||
| 1336 | /* Structure describing a block of memory which is sub-allocated to | 1357 | /* Structure describing a block of memory which is sub-allocated to |
| 1337 | obtain string data memory for strings. Blocks for small strings | 1358 | obtain string data memory for strings. Blocks for small strings |
| @@ -1347,8 +1368,8 @@ struct sblock | |||
| 1347 | of the sblock if there isn't any space left in this block. */ | 1368 | of the sblock if there isn't any space left in this block. */ |
| 1348 | sdata *next_free; | 1369 | sdata *next_free; |
| 1349 | 1370 | ||
| 1350 | /* Start of data. */ | 1371 | /* String data. */ |
| 1351 | sdata first_data; | 1372 | sdata data[FLEXIBLE_ARRAY_MEMBER]; |
| 1352 | }; | 1373 | }; |
| 1353 | 1374 | ||
| 1354 | /* Number of Lisp strings in a string_block structure. The 1020 is | 1375 | /* Number of Lisp strings in a string_block structure. The 1020 is |
| @@ -1464,7 +1485,7 @@ static ptrdiff_t const STRING_BYTES_MAX = | |||
| 1464 | min (STRING_BYTES_BOUND, | 1485 | min (STRING_BYTES_BOUND, |
| 1465 | ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD | 1486 | ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD |
| 1466 | - GC_STRING_EXTRA | 1487 | - GC_STRING_EXTRA |
| 1467 | - offsetof (struct sblock, first_data) | 1488 | - offsetof (struct sblock, data) |
| 1468 | - SDATA_DATA_OFFSET) | 1489 | - SDATA_DATA_OFFSET) |
| 1469 | & ~(sizeof (EMACS_INT) - 1))); | 1490 | & ~(sizeof (EMACS_INT) - 1))); |
| 1470 | 1491 | ||
| @@ -1507,7 +1528,7 @@ check_sblock (struct sblock *b) | |||
| 1507 | 1528 | ||
| 1508 | end = b->next_free; | 1529 | end = b->next_free; |
| 1509 | 1530 | ||
| 1510 | for (from = &b->first_data; from < end; from = from_end) | 1531 | for (from = b->data; from < end; from = from_end) |
| 1511 | { | 1532 | { |
| 1512 | /* Compute the next FROM here because copying below may | 1533 | /* Compute the next FROM here because copying below may |
| 1513 | overwrite data we need to compute it. */ | 1534 | overwrite data we need to compute it. */ |
| @@ -1535,7 +1556,7 @@ check_string_bytes (bool all_p) | |||
| 1535 | 1556 | ||
| 1536 | for (b = large_sblocks; b; b = b->next) | 1557 | for (b = large_sblocks; b; b = b->next) |
| 1537 | { | 1558 | { |
| 1538 | struct Lisp_String *s = b->first_data.string; | 1559 | struct Lisp_String *s = b->data[0].string; |
| 1539 | if (s) | 1560 | if (s) |
| 1540 | string_bytes (s); | 1561 | string_bytes (s); |
| 1541 | } | 1562 | } |
| @@ -1669,7 +1690,7 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1669 | 1690 | ||
| 1670 | if (nbytes > LARGE_STRING_BYTES) | 1691 | if (nbytes > LARGE_STRING_BYTES) |
| 1671 | { | 1692 | { |
| 1672 | size_t size = offsetof (struct sblock, first_data) + needed; | 1693 | size_t size = offsetof (struct sblock, data) + needed; |
| 1673 | 1694 | ||
| 1674 | #ifdef DOUG_LEA_MALLOC | 1695 | #ifdef DOUG_LEA_MALLOC |
| 1675 | /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed | 1696 | /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed |
| @@ -1691,8 +1712,8 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1691 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | 1712 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); |
| 1692 | #endif | 1713 | #endif |
| 1693 | 1714 | ||
| 1694 | b->next_free = &b->first_data; | 1715 | b->next_free = b->data; |
| 1695 | b->first_data.string = NULL; | 1716 | b->data[0].string = NULL; |
| 1696 | b->next = large_sblocks; | 1717 | b->next = large_sblocks; |
| 1697 | large_sblocks = b; | 1718 | large_sblocks = b; |
| 1698 | } | 1719 | } |
| @@ -1703,8 +1724,8 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1703 | { | 1724 | { |
| 1704 | /* Not enough room in the current sblock. */ | 1725 | /* Not enough room in the current sblock. */ |
| 1705 | b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); | 1726 | b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); |
| 1706 | b->next_free = &b->first_data; | 1727 | b->next_free = b->data; |
| 1707 | b->first_data.string = NULL; | 1728 | b->data[0].string = NULL; |
| 1708 | b->next = NULL; | 1729 | b->next = NULL; |
| 1709 | 1730 | ||
| 1710 | if (current_sblock) | 1731 | if (current_sblock) |
| @@ -1858,7 +1879,7 @@ free_large_strings (void) | |||
| 1858 | { | 1879 | { |
| 1859 | next = b->next; | 1880 | next = b->next; |
| 1860 | 1881 | ||
| 1861 | if (b->first_data.string == NULL) | 1882 | if (b->data[0].string == NULL) |
| 1862 | lisp_free (b); | 1883 | lisp_free (b); |
| 1863 | else | 1884 | else |
| 1864 | { | 1885 | { |
| @@ -1885,7 +1906,7 @@ compact_small_strings (void) | |||
| 1885 | to, and TB_END is the end of TB. */ | 1906 | to, and TB_END is the end of TB. */ |
| 1886 | tb = oldest_sblock; | 1907 | tb = oldest_sblock; |
| 1887 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); | 1908 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1888 | to = &tb->first_data; | 1909 | to = tb->data; |
| 1889 | 1910 | ||
| 1890 | /* Step through the blocks from the oldest to the youngest. We | 1911 | /* Step through the blocks from the oldest to the youngest. We |
| 1891 | expect that old blocks will stabilize over time, so that less | 1912 | expect that old blocks will stabilize over time, so that less |
| @@ -1895,7 +1916,7 @@ compact_small_strings (void) | |||
| 1895 | end = b->next_free; | 1916 | end = b->next_free; |
| 1896 | eassert ((char *) end <= (char *) b + SBLOCK_SIZE); | 1917 | eassert ((char *) end <= (char *) b + SBLOCK_SIZE); |
| 1897 | 1918 | ||
| 1898 | for (from = &b->first_data; from < end; from = from_end) | 1919 | for (from = b->data; from < end; from = from_end) |
| 1899 | { | 1920 | { |
| 1900 | /* Compute the next FROM here because copying below may | 1921 | /* Compute the next FROM here because copying below may |
| 1901 | overwrite data we need to compute it. */ | 1922 | overwrite data we need to compute it. */ |
| @@ -1932,7 +1953,7 @@ compact_small_strings (void) | |||
| 1932 | tb->next_free = to; | 1953 | tb->next_free = to; |
| 1933 | tb = tb->next; | 1954 | tb = tb->next; |
| 1934 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); | 1955 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1935 | to = &tb->first_data; | 1956 | to = tb->data; |
| 1936 | to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); | 1957 | to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1937 | } | 1958 | } |
| 1938 | 1959 | ||
| @@ -2020,82 +2041,61 @@ INIT must be an integer that represents a character. */) | |||
| 2020 | return val; | 2041 | return val; |
| 2021 | } | 2042 | } |
| 2022 | 2043 | ||
| 2023 | verify (sizeof (size_t) * CHAR_BIT == BITS_PER_BITS_WORD); | 2044 | /* Fill A with 1 bits if INIT is non-nil, and with 0 bits otherwise. |
| 2024 | verify ((BITS_PER_BITS_WORD & (BITS_PER_BITS_WORD - 1)) == 0); | 2045 | Return A. */ |
| 2025 | 2046 | ||
| 2026 | static ptrdiff_t | 2047 | Lisp_Object |
| 2027 | bool_vector_payload_bytes (ptrdiff_t nr_bits, | 2048 | bool_vector_fill (Lisp_Object a, Lisp_Object init) |
| 2028 | ptrdiff_t *exact_needed_bytes_out) | ||
| 2029 | { | 2049 | { |
| 2030 | ptrdiff_t exact_needed_bytes; | 2050 | EMACS_INT nbits = bool_vector_size (a); |
| 2031 | ptrdiff_t needed_bytes; | 2051 | if (0 < nbits) |
| 2032 | |||
| 2033 | eassume (nr_bits >= 0); | ||
| 2034 | |||
| 2035 | exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT; | ||
| 2036 | needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_BITS_WORD) / CHAR_BIT; | ||
| 2037 | |||
| 2038 | if (needed_bytes == 0) | ||
| 2039 | { | 2052 | { |
| 2040 | /* Always allocate at least one machine word of payload so that | 2053 | unsigned char *data = bool_vector_uchar_data (a); |
| 2041 | bool-vector operations in data.c don't need a special case | 2054 | int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; |
| 2042 | for empty vectors. */ | 2055 | ptrdiff_t nbytes = bool_vector_bytes (nbits); |
| 2043 | needed_bytes = sizeof (bits_word); | 2056 | int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); |
| 2057 | memset (data, pattern, nbytes - 1); | ||
| 2058 | data[nbytes - 1] = pattern & last_mask; | ||
| 2044 | } | 2059 | } |
| 2045 | 2060 | return a; | |
| 2046 | if (exact_needed_bytes_out != NULL) | ||
| 2047 | *exact_needed_bytes_out = exact_needed_bytes; | ||
| 2048 | |||
| 2049 | return needed_bytes; | ||
| 2050 | } | 2061 | } |
| 2051 | 2062 | ||
| 2052 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | 2063 | /* Return a newly allocated, uninitialized bool vector of size NBITS. */ |
| 2053 | doc: /* Return a new bool-vector of length LENGTH, using INIT for each element. | 2064 | |
| 2054 | LENGTH must be a number. INIT matters only in whether it is t or nil. */) | 2065 | Lisp_Object |
| 2055 | (Lisp_Object length, Lisp_Object init) | 2066 | make_uninit_bool_vector (EMACS_INT nbits) |
| 2056 | { | 2067 | { |
| 2057 | register Lisp_Object val; | 2068 | Lisp_Object val; |
| 2058 | struct Lisp_Bool_Vector *p; | 2069 | struct Lisp_Bool_Vector *p; |
| 2059 | ptrdiff_t exact_payload_bytes; | 2070 | EMACS_INT word_bytes, needed_elements; |
| 2060 | ptrdiff_t total_payload_bytes; | 2071 | word_bytes = bool_vector_words (nbits) * sizeof (bits_word); |
| 2061 | ptrdiff_t needed_elements; | 2072 | needed_elements = ((bool_header_size - header_size + word_bytes |
| 2062 | 2073 | + word_size - 1) | |
| 2063 | CHECK_NATNUM (length); | 2074 | / word_size); |
| 2064 | if (PTRDIFF_MAX < XFASTINT (length)) | ||
| 2065 | memory_full (SIZE_MAX); | ||
| 2066 | |||
| 2067 | total_payload_bytes = bool_vector_payload_bytes | ||
| 2068 | (XFASTINT (length), &exact_payload_bytes); | ||
| 2069 | |||
| 2070 | eassume (exact_payload_bytes <= total_payload_bytes); | ||
| 2071 | eassume (0 <= exact_payload_bytes); | ||
| 2072 | |||
| 2073 | needed_elements = ROUNDUP ((size_t) ((bool_header_size - header_size) | ||
| 2074 | + total_payload_bytes), | ||
| 2075 | word_size) / word_size; | ||
| 2076 | |||
| 2077 | p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); | 2075 | p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); |
| 2078 | XSETVECTOR (val, p); | 2076 | XSETVECTOR (val, p); |
| 2079 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); | 2077 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); |
| 2080 | 2078 | p->size = nbits; | |
| 2081 | p->size = XFASTINT (length); | ||
| 2082 | if (exact_payload_bytes) | ||
| 2083 | { | ||
| 2084 | memset (p->data, ! NILP (init) ? -1 : 0, exact_payload_bytes); | ||
| 2085 | |||
| 2086 | /* Clear any extraneous bits in the last byte. */ | ||
| 2087 | p->data[exact_payload_bytes - 1] | ||
| 2088 | &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1; | ||
| 2089 | } | ||
| 2090 | 2079 | ||
| 2091 | /* Clear padding at the end. */ | 2080 | /* Clear padding at the end. */ |
| 2092 | memset (p->data + exact_payload_bytes, | 2081 | if (nbits) |
| 2093 | 0, | 2082 | p->data[bool_vector_words (nbits) - 1] = 0; |
| 2094 | total_payload_bytes - exact_payload_bytes); | ||
| 2095 | 2083 | ||
| 2096 | return val; | 2084 | return val; |
| 2097 | } | 2085 | } |
| 2098 | 2086 | ||
| 2087 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | ||
| 2088 | doc: /* Return a new bool-vector of length LENGTH, using INIT for each element. | ||
| 2089 | LENGTH must be a number. INIT matters only in whether it is t or nil. */) | ||
| 2090 | (Lisp_Object length, Lisp_Object init) | ||
| 2091 | { | ||
| 2092 | Lisp_Object val; | ||
| 2093 | |||
| 2094 | CHECK_NATNUM (length); | ||
| 2095 | val = make_uninit_bool_vector (XFASTINT (length)); | ||
| 2096 | return bool_vector_fill (val, init); | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | 2099 | ||
| 2100 | /* Make a string from NBYTES bytes at CONTENTS, and compute the number | 2100 | /* Make a string from NBYTES bytes at CONTENTS, and compute the number |
| 2101 | of characters from the contents. This string may be unibyte or | 2101 | of characters from the contents. This string may be unibyte or |
| @@ -2606,16 +2606,35 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, | |||
| 2606 | Vector Allocation | 2606 | Vector Allocation |
| 2607 | ***********************************************************************/ | 2607 | ***********************************************************************/ |
| 2608 | 2608 | ||
| 2609 | /* Sometimes a vector's contents are merely a pointer internally used | ||
| 2610 | in vector allocation code. Usually you don't want to touch this. */ | ||
| 2611 | |||
| 2612 | static struct Lisp_Vector * | ||
| 2613 | next_vector (struct Lisp_Vector *v) | ||
| 2614 | { | ||
| 2615 | return XUNTAG (v->contents[0], 0); | ||
| 2616 | } | ||
| 2617 | |||
| 2618 | static void | ||
| 2619 | set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p) | ||
| 2620 | { | ||
| 2621 | v->contents[0] = make_lisp_ptr (p, 0); | ||
| 2622 | } | ||
| 2623 | |||
| 2609 | /* This value is balanced well enough to avoid too much internal overhead | 2624 | /* This value is balanced well enough to avoid too much internal overhead |
| 2610 | for the most common cases; it's not required to be a power of two, but | 2625 | for the most common cases; it's not required to be a power of two, but |
| 2611 | it's expected to be a mult-of-ROUNDUP_SIZE (see below). */ | 2626 | it's expected to be a mult-of-ROUNDUP_SIZE (see below). */ |
| 2612 | 2627 | ||
| 2613 | #define VECTOR_BLOCK_SIZE 4096 | 2628 | #define VECTOR_BLOCK_SIZE 4096 |
| 2614 | 2629 | ||
| 2615 | /* Align allocation request sizes to be a multiple of ROUNDUP_SIZE. */ | ||
| 2616 | enum | 2630 | enum |
| 2617 | { | 2631 | { |
| 2618 | roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? GCALIGNMENT : 1) | 2632 | /* Alignment of struct Lisp_Vector objects. */ |
| 2633 | vector_alignment = COMMON_MULTIPLE (ALIGNOF_STRUCT_LISP_VECTOR, | ||
| 2634 | USE_LSB_TAG ? GCALIGNMENT : 1), | ||
| 2635 | |||
| 2636 | /* Vector size requests are a multiple of this. */ | ||
| 2637 | roundup_size = COMMON_MULTIPLE (vector_alignment, word_size) | ||
| 2619 | }; | 2638 | }; |
| 2620 | 2639 | ||
| 2621 | /* Verify assumptions described above. */ | 2640 | /* Verify assumptions described above. */ |
| @@ -2623,7 +2642,7 @@ verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); | |||
| 2623 | verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | 2642 | verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); |
| 2624 | 2643 | ||
| 2625 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */ | 2644 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */ |
| 2626 | #define vroundup_ct(x) ROUNDUP ((size_t) (x), roundup_size) | 2645 | #define vroundup_ct(x) ROUNDUP (x, roundup_size) |
| 2627 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */ | 2646 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */ |
| 2628 | #define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x)) | 2647 | #define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x)) |
| 2629 | 2648 | ||
| @@ -2663,26 +2682,37 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | |||
| 2663 | eassert ((nbytes) % roundup_size == 0); \ | 2682 | eassert ((nbytes) % roundup_size == 0); \ |
| 2664 | (tmp) = VINDEX (nbytes); \ | 2683 | (tmp) = VINDEX (nbytes); \ |
| 2665 | eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \ | 2684 | eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \ |
| 2666 | v->u.next = vector_free_lists[tmp]; \ | 2685 | set_next_vector (v, vector_free_lists[tmp]); \ |
| 2667 | vector_free_lists[tmp] = (v); \ | 2686 | vector_free_lists[tmp] = (v); \ |
| 2668 | total_free_vector_slots += (nbytes) / word_size; \ | 2687 | total_free_vector_slots += (nbytes) / word_size; \ |
| 2669 | } while (0) | 2688 | } while (0) |
| 2670 | 2689 | ||
| 2671 | /* This internal type is used to maintain the list of large vectors | 2690 | /* This internal type is used to maintain the list of large vectors |
| 2672 | which are allocated at their own, e.g. outside of vector blocks. */ | 2691 | which are allocated at their own, e.g. outside of vector blocks. |
| 2692 | |||
| 2693 | struct large_vector itself cannot contain a struct Lisp_Vector, as | ||
| 2694 | the latter contains a flexible array member and C99 does not allow | ||
| 2695 | such structs to be nested. Instead, each struct large_vector | ||
| 2696 | object LV is followed by a struct Lisp_Vector, which is at offset | ||
| 2697 | large_vector_offset from LV, and whose address is therefore | ||
| 2698 | large_vector_vec (&LV). */ | ||
| 2673 | 2699 | ||
| 2674 | struct large_vector | 2700 | struct large_vector |
| 2675 | { | 2701 | { |
| 2676 | union { | 2702 | struct large_vector *next; |
| 2677 | struct large_vector *vector; | ||
| 2678 | #if USE_LSB_TAG | ||
| 2679 | /* We need to maintain ROUNDUP_SIZE alignment for the vector member. */ | ||
| 2680 | unsigned char c[vroundup_ct (sizeof (struct large_vector *))]; | ||
| 2681 | #endif | ||
| 2682 | } next; | ||
| 2683 | struct Lisp_Vector v; | ||
| 2684 | }; | 2703 | }; |
| 2685 | 2704 | ||
| 2705 | enum | ||
| 2706 | { | ||
| 2707 | large_vector_offset = ROUNDUP (sizeof (struct large_vector), vector_alignment) | ||
| 2708 | }; | ||
| 2709 | |||
| 2710 | static struct Lisp_Vector * | ||
| 2711 | large_vector_vec (struct large_vector *p) | ||
| 2712 | { | ||
| 2713 | return (struct Lisp_Vector *) ((char *) p + large_vector_offset); | ||
| 2714 | } | ||
| 2715 | |||
| 2686 | /* This internal type is used to maintain an underlying storage | 2716 | /* This internal type is used to maintain an underlying storage |
| 2687 | for small vectors. */ | 2717 | for small vectors. */ |
| 2688 | 2718 | ||
| @@ -2760,7 +2790,7 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2760 | if (vector_free_lists[index]) | 2790 | if (vector_free_lists[index]) |
| 2761 | { | 2791 | { |
| 2762 | vector = vector_free_lists[index]; | 2792 | vector = vector_free_lists[index]; |
| 2763 | vector_free_lists[index] = vector->u.next; | 2793 | vector_free_lists[index] = next_vector (vector); |
| 2764 | total_free_vector_slots -= nbytes / word_size; | 2794 | total_free_vector_slots -= nbytes / word_size; |
| 2765 | return vector; | 2795 | return vector; |
| 2766 | } | 2796 | } |
| @@ -2774,7 +2804,7 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2774 | { | 2804 | { |
| 2775 | /* This vector is larger than requested. */ | 2805 | /* This vector is larger than requested. */ |
| 2776 | vector = vector_free_lists[index]; | 2806 | vector = vector_free_lists[index]; |
| 2777 | vector_free_lists[index] = vector->u.next; | 2807 | vector_free_lists[index] = next_vector (vector); |
| 2778 | total_free_vector_slots -= nbytes / word_size; | 2808 | total_free_vector_slots -= nbytes / word_size; |
| 2779 | 2809 | ||
| 2780 | /* Excess bytes are used for the smaller vector, | 2810 | /* Excess bytes are used for the smaller vector, |
| @@ -2814,27 +2844,40 @@ static ptrdiff_t | |||
| 2814 | vector_nbytes (struct Lisp_Vector *v) | 2844 | vector_nbytes (struct Lisp_Vector *v) |
| 2815 | { | 2845 | { |
| 2816 | ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; | 2846 | ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; |
| 2847 | ptrdiff_t nwords; | ||
| 2817 | 2848 | ||
| 2818 | if (size & PSEUDOVECTOR_FLAG) | 2849 | if (size & PSEUDOVECTOR_FLAG) |
| 2819 | { | 2850 | { |
| 2820 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) | 2851 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) |
| 2821 | { | 2852 | { |
| 2822 | struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; | 2853 | struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; |
| 2823 | ptrdiff_t payload_bytes = | 2854 | ptrdiff_t word_bytes = (bool_vector_words (bv->size) |
| 2824 | bool_vector_payload_bytes (bv->size, NULL); | 2855 | * sizeof (bits_word)); |
| 2825 | 2856 | ptrdiff_t boolvec_bytes = bool_header_size + word_bytes; | |
| 2826 | eassume (payload_bytes >= 0); | 2857 | verify (header_size <= bool_header_size); |
| 2827 | size = bool_header_size + ROUNDUP (payload_bytes, word_size); | 2858 | nwords = (boolvec_bytes - header_size + word_size - 1) / word_size; |
| 2828 | } | 2859 | } |
| 2829 | else | 2860 | else |
| 2830 | size = (header_size | 2861 | nwords = ((size & PSEUDOVECTOR_SIZE_MASK) |
| 2831 | + ((size & PSEUDOVECTOR_SIZE_MASK) | 2862 | + ((size & PSEUDOVECTOR_REST_MASK) |
| 2832 | + ((size & PSEUDOVECTOR_REST_MASK) | 2863 | >> PSEUDOVECTOR_SIZE_BITS)); |
| 2833 | >> PSEUDOVECTOR_SIZE_BITS)) * word_size); | ||
| 2834 | } | 2864 | } |
| 2835 | else | 2865 | else |
| 2836 | size = header_size + size * word_size; | 2866 | nwords = size; |
| 2837 | return vroundup (size); | 2867 | return vroundup (header_size + word_size * nwords); |
| 2868 | } | ||
| 2869 | |||
| 2870 | /* Release extra resources still in use by VECTOR, which may be any | ||
| 2871 | vector-like object. For now, this is used just to free data in | ||
| 2872 | font objects. */ | ||
| 2873 | |||
| 2874 | static void | ||
| 2875 | cleanup_vector (struct Lisp_Vector *vector) | ||
| 2876 | { | ||
| 2877 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT) | ||
| 2878 | && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) | ||
| 2879 | == FONT_OBJECT_MAX)) | ||
| 2880 | ((struct font *) vector)->driver->close ((struct font *) vector); | ||
| 2838 | } | 2881 | } |
| 2839 | 2882 | ||
| 2840 | /* Reclaim space used by unmarked vectors. */ | 2883 | /* Reclaim space used by unmarked vectors. */ |
| @@ -2871,6 +2914,7 @@ sweep_vectors (void) | |||
| 2871 | { | 2914 | { |
| 2872 | ptrdiff_t total_bytes; | 2915 | ptrdiff_t total_bytes; |
| 2873 | 2916 | ||
| 2917 | cleanup_vector (vector); | ||
| 2874 | nbytes = vector_nbytes (vector); | 2918 | nbytes = vector_nbytes (vector); |
| 2875 | total_bytes = nbytes; | 2919 | total_bytes = nbytes; |
| 2876 | next = ADVANCE (vector, nbytes); | 2920 | next = ADVANCE (vector, nbytes); |
| @@ -2882,6 +2926,7 @@ sweep_vectors (void) | |||
| 2882 | { | 2926 | { |
| 2883 | if (VECTOR_MARKED_P (next)) | 2927 | if (VECTOR_MARKED_P (next)) |
| 2884 | break; | 2928 | break; |
| 2929 | cleanup_vector (next); | ||
| 2885 | nbytes = vector_nbytes (next); | 2930 | nbytes = vector_nbytes (next); |
| 2886 | total_bytes += nbytes; | 2931 | total_bytes += nbytes; |
| 2887 | next = ADVANCE (next, nbytes); | 2932 | next = ADVANCE (next, nbytes); |
| @@ -2918,7 +2963,7 @@ sweep_vectors (void) | |||
| 2918 | 2963 | ||
| 2919 | for (lv = large_vectors; lv; lv = *lvprev) | 2964 | for (lv = large_vectors; lv; lv = *lvprev) |
| 2920 | { | 2965 | { |
| 2921 | vector = &lv->v; | 2966 | vector = large_vector_vec (lv); |
| 2922 | if (VECTOR_MARKED_P (vector)) | 2967 | if (VECTOR_MARKED_P (vector)) |
| 2923 | { | 2968 | { |
| 2924 | VECTOR_UNMARK (vector); | 2969 | VECTOR_UNMARK (vector); |
| @@ -2934,11 +2979,11 @@ sweep_vectors (void) | |||
| 2934 | else | 2979 | else |
| 2935 | total_vector_slots | 2980 | total_vector_slots |
| 2936 | += header_size / word_size + vector->header.size; | 2981 | += header_size / word_size + vector->header.size; |
| 2937 | lvprev = &lv->next.vector; | 2982 | lvprev = &lv->next; |
| 2938 | } | 2983 | } |
| 2939 | else | 2984 | else |
| 2940 | { | 2985 | { |
| 2941 | *lvprev = lv->next.vector; | 2986 | *lvprev = lv->next; |
| 2942 | lisp_free (lv); | 2987 | lisp_free (lv); |
| 2943 | } | 2988 | } |
| 2944 | } | 2989 | } |
| @@ -2972,12 +3017,12 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 2972 | else | 3017 | else |
| 2973 | { | 3018 | { |
| 2974 | struct large_vector *lv | 3019 | struct large_vector *lv |
| 2975 | = lisp_malloc ((offsetof (struct large_vector, v.u.contents) | 3020 | = lisp_malloc ((large_vector_offset + header_size |
| 2976 | + len * word_size), | 3021 | + len * word_size), |
| 2977 | MEM_TYPE_VECTORLIKE); | 3022 | MEM_TYPE_VECTORLIKE); |
| 2978 | lv->next.vector = large_vectors; | 3023 | lv->next = large_vectors; |
| 2979 | large_vectors = lv; | 3024 | large_vectors = lv; |
| 2980 | p = &lv->v; | 3025 | p = large_vector_vec (lv); |
| 2981 | } | 3026 | } |
| 2982 | 3027 | ||
| 2983 | #ifdef DOUG_LEA_MALLOC | 3028 | #ifdef DOUG_LEA_MALLOC |
| @@ -3026,7 +3071,7 @@ allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag) | |||
| 3026 | 3071 | ||
| 3027 | /* Only the first lisplen slots will be traced normally by the GC. */ | 3072 | /* Only the first lisplen slots will be traced normally by the GC. */ |
| 3028 | for (i = 0; i < lisplen; ++i) | 3073 | for (i = 0; i < lisplen; ++i) |
| 3029 | v->u.contents[i] = Qnil; | 3074 | v->contents[i] = Qnil; |
| 3030 | 3075 | ||
| 3031 | XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen); | 3076 | XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen); |
| 3032 | return v; | 3077 | return v; |
| @@ -3114,7 +3159,7 @@ See also the function `vector'. */) | |||
| 3114 | p = allocate_vector (XFASTINT (length)); | 3159 | p = allocate_vector (XFASTINT (length)); |
| 3115 | sizei = XFASTINT (length); | 3160 | sizei = XFASTINT (length); |
| 3116 | for (i = 0; i < sizei; i++) | 3161 | for (i = 0; i < sizei; i++) |
| 3117 | p->u.contents[i] = init; | 3162 | p->contents[i] = init; |
| 3118 | 3163 | ||
| 3119 | XSETVECTOR (vector, p); | 3164 | XSETVECTOR (vector, p); |
| 3120 | return vector; | 3165 | return vector; |
| @@ -3132,7 +3177,7 @@ usage: (vector &rest OBJECTS) */) | |||
| 3132 | register struct Lisp_Vector *p = XVECTOR (val); | 3177 | register struct Lisp_Vector *p = XVECTOR (val); |
| 3133 | 3178 | ||
| 3134 | for (i = 0; i < nargs; i++) | 3179 | for (i = 0; i < nargs; i++) |
| 3135 | p->u.contents[i] = args[i]; | 3180 | p->contents[i] = args[i]; |
| 3136 | return val; | 3181 | return val; |
| 3137 | } | 3182 | } |
| 3138 | 3183 | ||
| @@ -3141,14 +3186,14 @@ make_byte_code (struct Lisp_Vector *v) | |||
| 3141 | { | 3186 | { |
| 3142 | /* Don't allow the global zero_vector to become a byte code object. */ | 3187 | /* Don't allow the global zero_vector to become a byte code object. */ |
| 3143 | eassert(0 < v->header.size); | 3188 | eassert(0 < v->header.size); |
| 3144 | if (v->header.size > 1 && STRINGP (v->u.contents[1]) | 3189 | if (v->header.size > 1 && STRINGP (v->contents[1]) |
| 3145 | && STRING_MULTIBYTE (v->u.contents[1])) | 3190 | && STRING_MULTIBYTE (v->contents[1])) |
| 3146 | /* BYTECODE-STRING must have been produced by Emacs 20.2 or the | 3191 | /* BYTECODE-STRING must have been produced by Emacs 20.2 or the |
| 3147 | earlier because they produced a raw 8-bit string for byte-code | 3192 | earlier because they produced a raw 8-bit string for byte-code |
| 3148 | and now such a byte-code string is loaded as multibyte while | 3193 | and now such a byte-code string is loaded as multibyte while |
| 3149 | raw 8-bit characters converted to multibyte form. Thus, now we | 3194 | raw 8-bit characters converted to multibyte form. Thus, now we |
| 3150 | must convert them back to the original unibyte form. */ | 3195 | must convert them back to the original unibyte form. */ |
| 3151 | v->u.contents[1] = Fstring_as_unibyte (v->u.contents[1]); | 3196 | v->contents[1] = Fstring_as_unibyte (v->contents[1]); |
| 3152 | XSETPVECTYPE (v, PVEC_COMPILED); | 3197 | XSETPVECTYPE (v, PVEC_COMPILED); |
| 3153 | } | 3198 | } |
| 3154 | 3199 | ||
| @@ -3183,7 +3228,7 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3183 | to be setcar'd). */ | 3228 | to be setcar'd). */ |
| 3184 | 3229 | ||
| 3185 | for (i = 0; i < nargs; i++) | 3230 | for (i = 0; i < nargs; i++) |
| 3186 | p->u.contents[i] = args[i]; | 3231 | p->contents[i] = args[i]; |
| 3187 | make_byte_code (p); | 3232 | make_byte_code (p); |
| 3188 | XSETCOMPILED (val, p); | 3233 | XSETCOMPILED (val, p); |
| 3189 | return val; | 3234 | return val; |
| @@ -4241,9 +4286,7 @@ live_vector_p (struct mem_node *m, void *p) | |||
| 4241 | vector = ADVANCE (vector, vector_nbytes (vector)); | 4286 | vector = ADVANCE (vector, vector_nbytes (vector)); |
| 4242 | } | 4287 | } |
| 4243 | } | 4288 | } |
| 4244 | else if (m->type == MEM_TYPE_VECTORLIKE | 4289 | else if (m->type == MEM_TYPE_VECTORLIKE && p == large_vector_vec (m->start)) |
| 4245 | && (char *) p == ((char *) m->start | ||
| 4246 | + offsetof (struct large_vector, v))) | ||
| 4247 | /* This memory node corresponds to a large vector. */ | 4290 | /* This memory node corresponds to a large vector. */ |
| 4248 | return 1; | 4291 | return 1; |
| 4249 | return 0; | 4292 | return 0; |
| @@ -5174,7 +5217,7 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 5174 | size &= PSEUDOVECTOR_SIZE_MASK; | 5217 | size &= PSEUDOVECTOR_SIZE_MASK; |
| 5175 | vec = XVECTOR (make_pure_vector (size)); | 5218 | vec = XVECTOR (make_pure_vector (size)); |
| 5176 | for (i = 0; i < size; i++) | 5219 | for (i = 0; i < size; i++) |
| 5177 | vec->u.contents[i] = Fpurecopy (AREF (obj, i)); | 5220 | vec->contents[i] = Fpurecopy (AREF (obj, i)); |
| 5178 | if (COMPILEDP (obj)) | 5221 | if (COMPILEDP (obj)) |
| 5179 | { | 5222 | { |
| 5180 | XSETPVECTYPE (vec, PVEC_COMPILED); | 5223 | XSETPVECTYPE (vec, PVEC_COMPILED); |
| @@ -5254,6 +5297,95 @@ total_bytes_of_live_objects (void) | |||
| 5254 | return tot; | 5297 | return tot; |
| 5255 | } | 5298 | } |
| 5256 | 5299 | ||
| 5300 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 5301 | |||
| 5302 | /* Remove unmarked font-spec and font-entity objects from ENTRY, which is | ||
| 5303 | (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...), and return changed entry. */ | ||
| 5304 | |||
| 5305 | static Lisp_Object | ||
| 5306 | compact_font_cache_entry (Lisp_Object entry) | ||
| 5307 | { | ||
| 5308 | Lisp_Object tail, *prev = &entry; | ||
| 5309 | |||
| 5310 | for (tail = entry; CONSP (tail); tail = XCDR (tail)) | ||
| 5311 | { | ||
| 5312 | bool drop = 0; | ||
| 5313 | Lisp_Object obj = XCAR (tail); | ||
| 5314 | |||
| 5315 | /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]). */ | ||
| 5316 | if (CONSP (obj) && FONT_SPEC_P (XCAR (obj)) | ||
| 5317 | && !VECTOR_MARKED_P (XFONT_SPEC (XCAR (obj))) | ||
| 5318 | && VECTORP (XCDR (obj))) | ||
| 5319 | { | ||
| 5320 | ptrdiff_t i, size = ASIZE (XCDR (obj)) & ~ARRAY_MARK_FLAG; | ||
| 5321 | |||
| 5322 | /* If font-spec is not marked, most likely all font-entities | ||
| 5323 | are not marked too. But we must be sure that nothing is | ||
| 5324 | marked within OBJ before we really drop it. */ | ||
| 5325 | for (i = 0; i < size; i++) | ||
| 5326 | if (VECTOR_MARKED_P (XFONT_ENTITY (AREF (XCDR (obj), i)))) | ||
| 5327 | break; | ||
| 5328 | |||
| 5329 | if (i == size) | ||
| 5330 | drop = 1; | ||
| 5331 | } | ||
| 5332 | if (drop) | ||
| 5333 | *prev = XCDR (tail); | ||
| 5334 | else | ||
| 5335 | prev = xcdr_addr (tail); | ||
| 5336 | } | ||
| 5337 | return entry; | ||
| 5338 | } | ||
| 5339 | |||
| 5340 | /* Compact font caches on all terminals and mark | ||
| 5341 | everything which is still here after compaction. */ | ||
| 5342 | |||
| 5343 | static void | ||
| 5344 | compact_font_caches (void) | ||
| 5345 | { | ||
| 5346 | struct terminal *t; | ||
| 5347 | |||
| 5348 | for (t = terminal_list; t; t = t->next_terminal) | ||
| 5349 | { | ||
| 5350 | Lisp_Object cache = TERMINAL_FONT_CACHE (t); | ||
| 5351 | |||
| 5352 | if (CONSP (cache)) | ||
| 5353 | { | ||
| 5354 | Lisp_Object entry; | ||
| 5355 | |||
| 5356 | for (entry = XCDR (cache); CONSP (entry); entry = XCDR (entry)) | ||
| 5357 | XSETCAR (entry, compact_font_cache_entry (XCAR (entry))); | ||
| 5358 | } | ||
| 5359 | mark_object (cache); | ||
| 5360 | } | ||
| 5361 | } | ||
| 5362 | |||
| 5363 | #else /* not HAVE_WINDOW_SYSTEM */ | ||
| 5364 | |||
| 5365 | #define compact_font_caches() (void)(0) | ||
| 5366 | |||
| 5367 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 5368 | |||
| 5369 | /* Remove (MARKER . DATA) entries with unmarked MARKER | ||
| 5370 | from buffer undo LIST and return changed list. */ | ||
| 5371 | |||
| 5372 | static Lisp_Object | ||
| 5373 | compact_undo_list (Lisp_Object list) | ||
| 5374 | { | ||
| 5375 | Lisp_Object tail, *prev = &list; | ||
| 5376 | |||
| 5377 | for (tail = list; CONSP (tail); tail = XCDR (tail)) | ||
| 5378 | { | ||
| 5379 | if (CONSP (XCAR (tail)) | ||
| 5380 | && MARKERP (XCAR (XCAR (tail))) | ||
| 5381 | && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) | ||
| 5382 | *prev = XCDR (tail); | ||
| 5383 | else | ||
| 5384 | prev = xcdr_addr (tail); | ||
| 5385 | } | ||
| 5386 | return list; | ||
| 5387 | } | ||
| 5388 | |||
| 5257 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 5389 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| 5258 | doc: /* Reclaim storage for Lisp objects no longer needed. | 5390 | doc: /* Reclaim storage for Lisp objects no longer needed. |
| 5259 | Garbage collection happens automatically if you cons more than | 5391 | Garbage collection happens automatically if you cons more than |
| @@ -5392,46 +5524,19 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5392 | mark_stack (); | 5524 | mark_stack (); |
| 5393 | #endif | 5525 | #endif |
| 5394 | 5526 | ||
| 5395 | /* Everything is now marked, except for the things that require special | 5527 | /* Everything is now marked, except for the data in font caches |
| 5396 | finalization, i.e. the undo_list. | 5528 | and undo lists. They're compacted by removing an items which |
| 5397 | Look thru every buffer's undo list | 5529 | aren't reachable otherwise. */ |
| 5398 | for elements that update markers that were not marked, | 5530 | |
| 5399 | and delete them. */ | 5531 | compact_font_caches (); |
| 5532 | |||
| 5400 | FOR_EACH_BUFFER (nextb) | 5533 | FOR_EACH_BUFFER (nextb) |
| 5401 | { | 5534 | { |
| 5402 | /* If a buffer's undo list is Qt, that means that undo is | 5535 | if (!EQ (BVAR (nextb, undo_list), Qt)) |
| 5403 | turned off in that buffer. Calling truncate_undo_list on | 5536 | bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list))); |
| 5404 | Qt tends to return NULL, which effectively turns undo back on. | 5537 | /* Now that we have stripped the elements that need not be |
| 5405 | So don't call truncate_undo_list if undo_list is Qt. */ | 5538 | in the undo_list any more, we can finally mark the list. */ |
| 5406 | if (! EQ (nextb->INTERNAL_FIELD (undo_list), Qt)) | 5539 | mark_object (BVAR (nextb, undo_list)); |
| 5407 | { | ||
| 5408 | Lisp_Object tail, prev; | ||
| 5409 | tail = nextb->INTERNAL_FIELD (undo_list); | ||
| 5410 | prev = Qnil; | ||
| 5411 | while (CONSP (tail)) | ||
| 5412 | { | ||
| 5413 | if (CONSP (XCAR (tail)) | ||
| 5414 | && MARKERP (XCAR (XCAR (tail))) | ||
| 5415 | && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) | ||
| 5416 | { | ||
| 5417 | if (NILP (prev)) | ||
| 5418 | nextb->INTERNAL_FIELD (undo_list) = tail = XCDR (tail); | ||
| 5419 | else | ||
| 5420 | { | ||
| 5421 | tail = XCDR (tail); | ||
| 5422 | XSETCDR (prev, tail); | ||
| 5423 | } | ||
| 5424 | } | ||
| 5425 | else | ||
| 5426 | { | ||
| 5427 | prev = tail; | ||
| 5428 | tail = XCDR (tail); | ||
| 5429 | } | ||
| 5430 | } | ||
| 5431 | } | ||
| 5432 | /* Now that we have stripped the elements that need not be in the | ||
| 5433 | undo_list any more, we can finally mark the list. */ | ||
| 5434 | mark_object (nextb->INTERNAL_FIELD (undo_list)); | ||
| 5435 | } | 5540 | } |
| 5436 | 5541 | ||
| 5437 | gc_sweep (); | 5542 | gc_sweep (); |
| @@ -5603,30 +5708,6 @@ mark_glyph_matrix (struct glyph_matrix *matrix) | |||
| 5603 | } | 5708 | } |
| 5604 | } | 5709 | } |
| 5605 | 5710 | ||
| 5606 | |||
| 5607 | /* Mark Lisp faces in the face cache C. */ | ||
| 5608 | |||
| 5609 | static void | ||
| 5610 | mark_face_cache (struct face_cache *c) | ||
| 5611 | { | ||
| 5612 | if (c) | ||
| 5613 | { | ||
| 5614 | int i, j; | ||
| 5615 | for (i = 0; i < c->used; ++i) | ||
| 5616 | { | ||
| 5617 | struct face *face = FACE_FROM_ID (c->f, i); | ||
| 5618 | |||
| 5619 | if (face) | ||
| 5620 | { | ||
| 5621 | for (j = 0; j < LFACE_VECTOR_SIZE; ++j) | ||
| 5622 | mark_object (face->lface[j]); | ||
| 5623 | } | ||
| 5624 | } | ||
| 5625 | } | ||
| 5626 | } | ||
| 5627 | |||
| 5628 | |||
| 5629 | |||
| 5630 | /* Mark reference to a Lisp_Object. | 5711 | /* Mark reference to a Lisp_Object. |
| 5631 | If the object referred to has not been seen yet, recursively mark | 5712 | If the object referred to has not been seen yet, recursively mark |
| 5632 | all the references contained in it. */ | 5713 | all the references contained in it. */ |
| @@ -5657,7 +5738,7 @@ mark_vectorlike (struct Lisp_Vector *ptr) | |||
| 5657 | The distinction is used e.g. by Lisp_Process which places extra | 5738 | The distinction is used e.g. by Lisp_Process which places extra |
| 5658 | non-Lisp_Object fields at the end of the structure... */ | 5739 | non-Lisp_Object fields at the end of the structure... */ |
| 5659 | for (i = 0; i < size; i++) /* ...and then mark its elements. */ | 5740 | for (i = 0; i < size; i++) /* ...and then mark its elements. */ |
| 5660 | mark_object (ptr->u.contents[i]); | 5741 | mark_object (ptr->contents[i]); |
| 5661 | } | 5742 | } |
| 5662 | 5743 | ||
| 5663 | /* Like mark_vectorlike but optimized for char-tables (and | 5744 | /* Like mark_vectorlike but optimized for char-tables (and |
| @@ -5674,7 +5755,7 @@ mark_char_table (struct Lisp_Vector *ptr) | |||
| 5674 | VECTOR_MARK (ptr); | 5755 | VECTOR_MARK (ptr); |
| 5675 | for (i = 0; i < size; i++) | 5756 | for (i = 0; i < size; i++) |
| 5676 | { | 5757 | { |
| 5677 | Lisp_Object val = ptr->u.contents[i]; | 5758 | Lisp_Object val = ptr->contents[i]; |
| 5678 | 5759 | ||
| 5679 | if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->gcmarkbit)) | 5760 | if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->gcmarkbit)) |
| 5680 | continue; | 5761 | continue; |
| @@ -5726,6 +5807,30 @@ mark_buffer (struct buffer *buffer) | |||
| 5726 | mark_buffer (buffer->base_buffer); | 5807 | mark_buffer (buffer->base_buffer); |
| 5727 | } | 5808 | } |
| 5728 | 5809 | ||
| 5810 | /* Mark Lisp faces in the face cache C. */ | ||
| 5811 | |||
| 5812 | static void | ||
| 5813 | mark_face_cache (struct face_cache *c) | ||
| 5814 | { | ||
| 5815 | if (c) | ||
| 5816 | { | ||
| 5817 | int i, j; | ||
| 5818 | for (i = 0; i < c->used; ++i) | ||
| 5819 | { | ||
| 5820 | struct face *face = FACE_FROM_ID (c->f, i); | ||
| 5821 | |||
| 5822 | if (face) | ||
| 5823 | { | ||
| 5824 | if (face->font && !VECTOR_MARKED_P (face->font)) | ||
| 5825 | mark_vectorlike ((struct Lisp_Vector *) face->font); | ||
| 5826 | |||
| 5827 | for (j = 0; j < LFACE_VECTOR_SIZE; ++j) | ||
| 5828 | mark_object (face->lface[j]); | ||
| 5829 | } | ||
| 5830 | } | ||
| 5831 | } | ||
| 5832 | } | ||
| 5833 | |||
| 5729 | /* Remove killed buffers or items whose car is a killed buffer from | 5834 | /* Remove killed buffers or items whose car is a killed buffer from |
| 5730 | LIST, and mark other items. Return changed LIST, which is marked. */ | 5835 | LIST, and mark other items. Return changed LIST, which is marked. */ |
| 5731 | 5836 | ||
| @@ -5879,18 +5984,31 @@ mark_object (Lisp_Object arg) | |||
| 5879 | VECTOR_MARK (ptr); | 5984 | VECTOR_MARK (ptr); |
| 5880 | for (i = 0; i < size; i++) | 5985 | for (i = 0; i < size; i++) |
| 5881 | if (i != COMPILED_CONSTANTS) | 5986 | if (i != COMPILED_CONSTANTS) |
| 5882 | mark_object (ptr->u.contents[i]); | 5987 | mark_object (ptr->contents[i]); |
| 5883 | if (size > COMPILED_CONSTANTS) | 5988 | if (size > COMPILED_CONSTANTS) |
| 5884 | { | 5989 | { |
| 5885 | obj = ptr->u.contents[COMPILED_CONSTANTS]; | 5990 | obj = ptr->contents[COMPILED_CONSTANTS]; |
| 5886 | goto loop; | 5991 | goto loop; |
| 5887 | } | 5992 | } |
| 5888 | } | 5993 | } |
| 5889 | break; | 5994 | break; |
| 5890 | 5995 | ||
| 5891 | case PVEC_FRAME: | 5996 | case PVEC_FRAME: |
| 5892 | mark_vectorlike (ptr); | 5997 | { |
| 5893 | mark_face_cache (((struct frame *) ptr)->face_cache); | 5998 | struct frame *f = (struct frame *) ptr; |
| 5999 | |||
| 6000 | mark_vectorlike (ptr); | ||
| 6001 | mark_face_cache (f->face_cache); | ||
| 6002 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 6003 | if (FRAME_WINDOW_P (f) && FRAME_X_OUTPUT (f)) | ||
| 6004 | { | ||
| 6005 | struct font *font = FRAME_FONT (f); | ||
| 6006 | |||
| 6007 | if (font && !VECTOR_MARKED_P (font)) | ||
| 6008 | mark_vectorlike ((struct Lisp_Vector *) font); | ||
| 6009 | } | ||
| 6010 | #endif | ||
| 6011 | } | ||
| 5894 | break; | 6012 | break; |
| 5895 | 6013 | ||
| 5896 | case PVEC_WINDOW: | 6014 | case PVEC_WINDOW: |
| @@ -6118,9 +6236,6 @@ mark_terminals (void) | |||
| 6118 | it might have been marked already. Make sure the image cache | 6236 | it might have been marked already. Make sure the image cache |
| 6119 | gets marked. */ | 6237 | gets marked. */ |
| 6120 | mark_image_cache (t->image_cache); | 6238 | mark_image_cache (t->image_cache); |
| 6121 | /* FIXME: currently font cache may grow too large | ||
| 6122 | and probably needs special finalization. */ | ||
| 6123 | mark_object (TERMINAL_FONT_CACHE (t)); | ||
| 6124 | #endif /* HAVE_WINDOW_SYSTEM */ | 6239 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 6125 | if (!VECTOR_MARKED_P (t)) | 6240 | if (!VECTOR_MARKED_P (t)) |
| 6126 | mark_vectorlike ((struct Lisp_Vector *)t); | 6241 | mark_vectorlike ((struct Lisp_Vector *)t); |