diff options
| author | Bill Wohler | 2014-02-23 18:04:35 -0800 |
|---|---|---|
| committer | Bill Wohler | 2014-02-23 18:04:35 -0800 |
| commit | 3e93bafb95608467e438ba7f725fd1f020669f8c (patch) | |
| tree | f2f90109f283e06a18caea3cb2a2623abcfb3a92 /src/alloc.c | |
| parent | 791c0d7634e44bb92ca85af605be84ff2ae08963 (diff) | |
| parent | e918e27fdf331e89268fc2c9d7cf838d3ecf7aa7 (diff) | |
| download | emacs-3e93bafb95608467e438ba7f725fd1f020669f8c.tar.gz emacs-3e93bafb95608467e438ba7f725fd1f020669f8c.zip | |
Merge from trunk; up to 2014-02-23T23:41:17Z!lekktu@gmail.com.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 1054 |
1 files changed, 630 insertions, 424 deletions
diff --git a/src/alloc.c b/src/alloc.c index 80086433e65..7f0a74ca834 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* Storage allocation and gc for GNU Emacs Lisp interpreter. | 1 | /* Storage allocation and gc for GNU Emacs Lisp interpreter. |
| 2 | 2 | ||
| 3 | Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2013 Free Software | 3 | Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2014 Free Software |
| 4 | Foundation, Inc. | 4 | Foundation, Inc. |
| 5 | 5 | ||
| 6 | This file is part of GNU Emacs. | 6 | This file is part of GNU Emacs. |
| @@ -20,8 +20,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 20 | 20 | ||
| 21 | #include <config.h> | 21 | #include <config.h> |
| 22 | 22 | ||
| 23 | #define LISP_INLINE EXTERN_INLINE | ||
| 24 | |||
| 25 | #include <stdio.h> | 23 | #include <stdio.h> |
| 26 | #include <limits.h> /* For CHAR_BIT. */ | 24 | #include <limits.h> /* For CHAR_BIT. */ |
| 27 | 25 | ||
| @@ -44,9 +42,24 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 44 | #include "frame.h" | 42 | #include "frame.h" |
| 45 | #include "blockinput.h" | 43 | #include "blockinput.h" |
| 46 | #include "termhooks.h" /* For struct terminal. */ | 44 | #include "termhooks.h" /* For struct terminal. */ |
| 45 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 46 | #include TERM_HEADER | ||
| 47 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 47 | 48 | ||
| 48 | #include <verify.h> | 49 | #include <verify.h> |
| 49 | 50 | ||
| 51 | #if (defined ENABLE_CHECKING \ | ||
| 52 | && defined HAVE_VALGRIND_VALGRIND_H \ | ||
| 53 | && !defined USE_VALGRIND) | ||
| 54 | # define USE_VALGRIND 1 | ||
| 55 | #endif | ||
| 56 | |||
| 57 | #if USE_VALGRIND | ||
| 58 | #include <valgrind/valgrind.h> | ||
| 59 | #include <valgrind/memcheck.h> | ||
| 60 | static bool valgrind_p; | ||
| 61 | #endif | ||
| 62 | |||
| 50 | /* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. | 63 | /* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. |
| 51 | Doable only if GC_MARK_STACK. */ | 64 | Doable only if GC_MARK_STACK. */ |
| 52 | #if ! GC_MARK_STACK | 65 | #if ! GC_MARK_STACK |
| @@ -190,7 +203,27 @@ const char *pending_malloc_warning; | |||
| 190 | #if MAX_SAVE_STACK > 0 | 203 | #if MAX_SAVE_STACK > 0 |
| 191 | static char *stack_copy; | 204 | static char *stack_copy; |
| 192 | static ptrdiff_t stack_copy_size; | 205 | static ptrdiff_t stack_copy_size; |
| 193 | #endif | 206 | |
| 207 | /* Copy to DEST a block of memory from SRC of size SIZE bytes, | ||
| 208 | avoiding any address sanitization. */ | ||
| 209 | |||
| 210 | static void * ATTRIBUTE_NO_SANITIZE_ADDRESS | ||
| 211 | no_sanitize_memcpy (void *dest, void const *src, size_t size) | ||
| 212 | { | ||
| 213 | if (! ADDRESS_SANITIZER) | ||
| 214 | return memcpy (dest, src, size); | ||
| 215 | else | ||
| 216 | { | ||
| 217 | size_t i; | ||
| 218 | char *d = dest; | ||
| 219 | char const *s = src; | ||
| 220 | for (i = 0; i < size; i++) | ||
| 221 | d[i] = s[i]; | ||
| 222 | return dest; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | #endif /* MAX_SAVE_STACK > 0 */ | ||
| 194 | 227 | ||
| 195 | static Lisp_Object Qconses; | 228 | static Lisp_Object Qconses; |
| 196 | static Lisp_Object Qsymbols; | 229 | static Lisp_Object Qsymbols; |
| @@ -209,7 +242,6 @@ Lisp_Object Qchar_table_extra_slots; | |||
| 209 | 242 | ||
| 210 | static Lisp_Object Qpost_gc_hook; | 243 | static Lisp_Object Qpost_gc_hook; |
| 211 | 244 | ||
| 212 | static void free_save_value (Lisp_Object); | ||
| 213 | static void mark_terminals (void); | 245 | static void mark_terminals (void); |
| 214 | static void gc_sweep (void); | 246 | static void gc_sweep (void); |
| 215 | static Lisp_Object make_pure_vector (ptrdiff_t); | 247 | static Lisp_Object make_pure_vector (ptrdiff_t); |
| @@ -247,10 +279,6 @@ enum mem_type | |||
| 247 | 279 | ||
| 248 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK | 280 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK |
| 249 | 281 | ||
| 250 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | ||
| 251 | #include <stdio.h> /* For fprintf. */ | ||
| 252 | #endif | ||
| 253 | |||
| 254 | /* A unique object in pure space used to make some Lisp objects | 282 | /* A unique object in pure space used to make some Lisp objects |
| 255 | on free lists recognizable in O(1). */ | 283 | on free lists recognizable in O(1). */ |
| 256 | 284 | ||
| @@ -323,20 +351,6 @@ static void *min_heap_address, *max_heap_address; | |||
| 323 | static struct mem_node mem_z; | 351 | static struct mem_node mem_z; |
| 324 | #define MEM_NIL &mem_z | 352 | #define MEM_NIL &mem_z |
| 325 | 353 | ||
| 326 | static struct Lisp_Vector *allocate_vectorlike (ptrdiff_t); | ||
| 327 | static void lisp_free (void *); | ||
| 328 | static void mark_stack (void); | ||
| 329 | static bool live_vector_p (struct mem_node *, void *); | ||
| 330 | static bool live_buffer_p (struct mem_node *, void *); | ||
| 331 | static bool live_string_p (struct mem_node *, void *); | ||
| 332 | static bool live_cons_p (struct mem_node *, void *); | ||
| 333 | static bool live_symbol_p (struct mem_node *, void *); | ||
| 334 | static bool live_float_p (struct mem_node *, void *); | ||
| 335 | static bool live_misc_p (struct mem_node *, void *); | ||
| 336 | static void mark_maybe_object (Lisp_Object); | ||
| 337 | static void mark_memory (void *, void *); | ||
| 338 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK | ||
| 339 | static void mem_init (void); | ||
| 340 | static struct mem_node *mem_insert (void *, void *, enum mem_type); | 354 | static struct mem_node *mem_insert (void *, void *, enum mem_type); |
| 341 | static void mem_insert_fixup (struct mem_node *); | 355 | static void mem_insert_fixup (struct mem_node *); |
| 342 | static void mem_rotate_left (struct mem_node *); | 356 | static void mem_rotate_left (struct mem_node *); |
| @@ -344,12 +358,6 @@ static void mem_rotate_right (struct mem_node *); | |||
| 344 | static void mem_delete (struct mem_node *); | 358 | static void mem_delete (struct mem_node *); |
| 345 | static void mem_delete_fixup (struct mem_node *); | 359 | static void mem_delete_fixup (struct mem_node *); |
| 346 | static struct mem_node *mem_find (void *); | 360 | static struct mem_node *mem_find (void *); |
| 347 | #endif | ||
| 348 | |||
| 349 | |||
| 350 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | ||
| 351 | static void check_gcpros (void); | ||
| 352 | #endif | ||
| 353 | 361 | ||
| 354 | #endif /* GC_MARK_STACK || GC_MALLOC_CHECK */ | 362 | #endif /* GC_MARK_STACK || GC_MALLOC_CHECK */ |
| 355 | 363 | ||
| @@ -364,7 +372,7 @@ struct gcpro *gcprolist; | |||
| 364 | /* Addresses of staticpro'd variables. Initialize it to a nonzero | 372 | /* Addresses of staticpro'd variables. Initialize it to a nonzero |
| 365 | value; otherwise some compilers put it into BSS. */ | 373 | value; otherwise some compilers put it into BSS. */ |
| 366 | 374 | ||
| 367 | #define NSTATICS 0x800 | 375 | enum { NSTATICS = 2048 }; |
| 368 | static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag}; | 376 | static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag}; |
| 369 | 377 | ||
| 370 | /* Index of next unused slot in staticvec. */ | 378 | /* Index of next unused slot in staticvec. */ |
| @@ -373,14 +381,27 @@ static int staticidx; | |||
| 373 | 381 | ||
| 374 | static void *pure_alloc (size_t, int); | 382 | static void *pure_alloc (size_t, int); |
| 375 | 383 | ||
| 384 | /* Return X rounded to the next multiple of Y. Arguments should not | ||
| 385 | have side effects, as they are evaluated more than once. Assume X | ||
| 386 | + Y - 1 does not overflow. Tune for Y being a power of 2. */ | ||
| 376 | 387 | ||
| 377 | /* Value is SZ rounded up to the next multiple of ALIGNMENT. | 388 | #define ROUNDUP(x, y) ((y) & ((y) - 1) \ |
| 378 | ALIGNMENT must be a power of 2. */ | 389 | ? ((x) + (y) - 1) - ((x) + (y) - 1) % (y) \ |
| 390 | : ((x) + (y) - 1) & ~ ((y) - 1)) | ||
| 379 | 391 | ||
| 380 | #define ALIGN(ptr, ALIGNMENT) \ | 392 | /* Return PTR rounded up to the next multiple of ALIGNMENT. */ |
| 381 | ((void *) (((uintptr_t) (ptr) + (ALIGNMENT) - 1) \ | ||
| 382 | & ~ ((ALIGNMENT) - 1))) | ||
| 383 | 393 | ||
| 394 | static void * | ||
| 395 | ALIGN (void *ptr, int alignment) | ||
| 396 | { | ||
| 397 | return (void *) ROUNDUP ((uintptr_t) ptr, alignment); | ||
| 398 | } | ||
| 399 | |||
| 400 | static void | ||
| 401 | XFLOAT_INIT (Lisp_Object f, double n) | ||
| 402 | { | ||
| 403 | XFLOAT (f)->u.data = n; | ||
| 404 | } | ||
| 384 | 405 | ||
| 385 | 406 | ||
| 386 | /************************************************************************ | 407 | /************************************************************************ |
| @@ -422,11 +443,11 @@ buffer_memory_full (ptrdiff_t nbytes) | |||
| 422 | 443 | ||
| 423 | #ifndef REL_ALLOC | 444 | #ifndef REL_ALLOC |
| 424 | memory_full (nbytes); | 445 | memory_full (nbytes); |
| 425 | #endif | 446 | #else |
| 426 | |||
| 427 | /* This used to call error, but if we've run out of memory, we could | 447 | /* This used to call error, but if we've run out of memory, we could |
| 428 | get infinite recursion trying to build the string. */ | 448 | get infinite recursion trying to build the string. */ |
| 429 | xsignal (Qnil, Vmemory_signal_data); | 449 | xsignal (Qnil, Vmemory_signal_data); |
| 450 | #endif | ||
| 430 | } | 451 | } |
| 431 | 452 | ||
| 432 | /* A common multiple of the positive integers A and B. Ideally this | 453 | /* A common multiple of the positive integers A and B. Ideally this |
| @@ -814,10 +835,19 @@ xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, | |||
| 814 | char * | 835 | char * |
| 815 | xstrdup (const char *s) | 836 | xstrdup (const char *s) |
| 816 | { | 837 | { |
| 817 | size_t len = strlen (s) + 1; | 838 | ptrdiff_t size; |
| 818 | char *p = xmalloc (len); | 839 | eassert (s); |
| 819 | memcpy (p, s, len); | 840 | size = strlen (s) + 1; |
| 820 | return p; | 841 | return memcpy (xmalloc (size), s, size); |
| 842 | } | ||
| 843 | |||
| 844 | /* Like above, but duplicates Lisp string to C string. */ | ||
| 845 | |||
| 846 | char * | ||
| 847 | xlispstrdup (Lisp_Object string) | ||
| 848 | { | ||
| 849 | ptrdiff_t size = SBYTES (string) + 1; | ||
| 850 | return memcpy (xmalloc (size), SSDATA (string), size); | ||
| 821 | } | 851 | } |
| 822 | 852 | ||
| 823 | /* Like putenv, but (1) use the equivalent of xmalloc and (2) the | 853 | /* Like putenv, but (1) use the equivalent of xmalloc and (2) the |
| @@ -830,22 +860,13 @@ xputenv (char const *string) | |||
| 830 | memory_full (0); | 860 | memory_full (0); |
| 831 | } | 861 | } |
| 832 | 862 | ||
| 833 | /* Unwind for SAFE_ALLOCA */ | ||
| 834 | |||
| 835 | Lisp_Object | ||
| 836 | safe_alloca_unwind (Lisp_Object arg) | ||
| 837 | { | ||
| 838 | free_save_value (arg); | ||
| 839 | return Qnil; | ||
| 840 | } | ||
| 841 | |||
| 842 | /* Return a newly allocated memory block of SIZE bytes, remembering | 863 | /* Return a newly allocated memory block of SIZE bytes, remembering |
| 843 | to free it when unwinding. */ | 864 | to free it when unwinding. */ |
| 844 | void * | 865 | void * |
| 845 | record_xmalloc (size_t size) | 866 | record_xmalloc (size_t size) |
| 846 | { | 867 | { |
| 847 | void *p = xmalloc (size); | 868 | void *p = xmalloc (size); |
| 848 | record_unwind_protect (safe_alloca_unwind, make_save_pointer (p)); | 869 | record_unwind_protect_ptr (xfree, p); |
| 849 | return p; | 870 | return p; |
| 850 | } | 871 | } |
| 851 | 872 | ||
| @@ -919,8 +940,26 @@ lisp_free (void *block) | |||
| 919 | /* The entry point is lisp_align_malloc which returns blocks of at most | 940 | /* The entry point is lisp_align_malloc which returns blocks of at most |
| 920 | BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ | 941 | BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ |
| 921 | 942 | ||
| 922 | #if defined (HAVE_POSIX_MEMALIGN) && defined (SYSTEM_MALLOC) | 943 | /* Use aligned_alloc if it or a simple substitute is available. |
| 923 | #define USE_POSIX_MEMALIGN 1 | 944 | Address sanitization breaks aligned allocation, as of gcc 4.8.2 and |
| 945 | clang 3.3 anyway. */ | ||
| 946 | |||
| 947 | #if ! ADDRESS_SANITIZER | ||
| 948 | # if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC | ||
| 949 | # define USE_ALIGNED_ALLOC 1 | ||
| 950 | /* Defined in gmalloc.c. */ | ||
| 951 | void *aligned_alloc (size_t, size_t); | ||
| 952 | # elif defined HAVE_ALIGNED_ALLOC | ||
| 953 | # define USE_ALIGNED_ALLOC 1 | ||
| 954 | # elif defined HAVE_POSIX_MEMALIGN | ||
| 955 | # define USE_ALIGNED_ALLOC 1 | ||
| 956 | static void * | ||
| 957 | aligned_alloc (size_t alignment, size_t size) | ||
| 958 | { | ||
| 959 | void *p; | ||
| 960 | return posix_memalign (&p, alignment, size) == 0 ? p : 0; | ||
| 961 | } | ||
| 962 | # endif | ||
| 924 | #endif | 963 | #endif |
| 925 | 964 | ||
| 926 | /* BLOCK_ALIGN has to be a power of 2. */ | 965 | /* BLOCK_ALIGN has to be a power of 2. */ |
| @@ -930,7 +969,7 @@ lisp_free (void *block) | |||
| 930 | malloc a chance to minimize the amount of memory wasted to alignment. | 969 | malloc a chance to minimize the amount of memory wasted to alignment. |
| 931 | It should be tuned to the particular malloc library used. | 970 | It should be tuned to the particular malloc library used. |
| 932 | On glibc-2.3.2, malloc never tries to align, so a padding of 0 is best. | 971 | On glibc-2.3.2, malloc never tries to align, so a padding of 0 is best. |
| 933 | posix_memalign on the other hand would ideally prefer a value of 4 | 972 | aligned_alloc on the other hand would ideally prefer a value of 4 |
| 934 | because otherwise, there's 1020 bytes wasted between each ablocks. | 973 | because otherwise, there's 1020 bytes wasted between each ablocks. |
| 935 | In Emacs, testing shows that those 1020 can most of the time be | 974 | In Emacs, testing shows that those 1020 can most of the time be |
| 936 | efficiently used by malloc to place other objects, so a value of 0 can | 975 | efficiently used by malloc to place other objects, so a value of 0 can |
| @@ -975,7 +1014,7 @@ struct ablocks | |||
| 975 | struct ablock blocks[ABLOCKS_SIZE]; | 1014 | struct ablock blocks[ABLOCKS_SIZE]; |
| 976 | }; | 1015 | }; |
| 977 | 1016 | ||
| 978 | /* Size of the block requested from malloc or posix_memalign. */ | 1017 | /* Size of the block requested from malloc or aligned_alloc. */ |
| 979 | #define ABLOCKS_BYTES (sizeof (struct ablocks) - BLOCK_PADDING) | 1018 | #define ABLOCKS_BYTES (sizeof (struct ablocks) - BLOCK_PADDING) |
| 980 | 1019 | ||
| 981 | #define ABLOCK_ABASE(block) \ | 1020 | #define ABLOCK_ABASE(block) \ |
| @@ -987,11 +1026,11 @@ struct ablocks | |||
| 987 | #define ABLOCKS_BUSY(abase) ((abase)->blocks[0].abase) | 1026 | #define ABLOCKS_BUSY(abase) ((abase)->blocks[0].abase) |
| 988 | 1027 | ||
| 989 | /* Pointer to the (not necessarily aligned) malloc block. */ | 1028 | /* Pointer to the (not necessarily aligned) malloc block. */ |
| 990 | #ifdef USE_POSIX_MEMALIGN | 1029 | #ifdef USE_ALIGNED_ALLOC |
| 991 | #define ABLOCKS_BASE(abase) (abase) | 1030 | #define ABLOCKS_BASE(abase) (abase) |
| 992 | #else | 1031 | #else |
| 993 | #define ABLOCKS_BASE(abase) \ | 1032 | #define ABLOCKS_BASE(abase) \ |
| 994 | (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void**)abase)[-1]) | 1033 | (1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **)abase)[-1]) |
| 995 | #endif | 1034 | #endif |
| 996 | 1035 | ||
| 997 | /* The list of free ablock. */ | 1036 | /* The list of free ablock. */ |
| @@ -1026,13 +1065,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) | |||
| 1026 | mallopt (M_MMAP_MAX, 0); | 1065 | mallopt (M_MMAP_MAX, 0); |
| 1027 | #endif | 1066 | #endif |
| 1028 | 1067 | ||
| 1029 | #ifdef USE_POSIX_MEMALIGN | 1068 | #ifdef USE_ALIGNED_ALLOC |
| 1030 | { | 1069 | abase = base = aligned_alloc (BLOCK_ALIGN, ABLOCKS_BYTES); |
| 1031 | int err = posix_memalign (&base, BLOCK_ALIGN, ABLOCKS_BYTES); | ||
| 1032 | if (err) | ||
| 1033 | base = NULL; | ||
| 1034 | abase = base; | ||
| 1035 | } | ||
| 1036 | #else | 1070 | #else |
| 1037 | base = malloc (ABLOCKS_BYTES); | 1071 | base = malloc (ABLOCKS_BYTES); |
| 1038 | abase = ALIGN (base, BLOCK_ALIGN); | 1072 | abase = ALIGN (base, BLOCK_ALIGN); |
| @@ -1046,7 +1080,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) | |||
| 1046 | 1080 | ||
| 1047 | aligned = (base == abase); | 1081 | aligned = (base == abase); |
| 1048 | if (!aligned) | 1082 | if (!aligned) |
| 1049 | ((void**)abase)[-1] = base; | 1083 | ((void **) abase)[-1] = base; |
| 1050 | 1084 | ||
| 1051 | #ifdef DOUG_LEA_MALLOC | 1085 | #ifdef DOUG_LEA_MALLOC |
| 1052 | /* Back to a reasonable maximum of mmap'ed areas. */ | 1086 | /* Back to a reasonable maximum of mmap'ed areas. */ |
| @@ -1162,7 +1196,7 @@ lisp_align_free (void *block) | |||
| 1162 | #define INTERVAL_BLOCK_SIZE \ | 1196 | #define INTERVAL_BLOCK_SIZE \ |
| 1163 | ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval)) | 1197 | ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval)) |
| 1164 | 1198 | ||
| 1165 | /* Intervals are allocated in chunks in form of an interval_block | 1199 | /* Intervals are allocated in chunks in the form of an interval_block |
| 1166 | structure. */ | 1200 | structure. */ |
| 1167 | 1201 | ||
| 1168 | struct interval_block | 1202 | struct interval_block |
| @@ -1273,7 +1307,7 @@ mark_interval (register INTERVAL i, Lisp_Object dummy) | |||
| 1273 | When a Lisp_String is freed during GC, it is put back on | 1307 | When a Lisp_String is freed during GC, it is put back on |
| 1274 | string_free_list, and its `data' member and its sdata's `string' | 1308 | string_free_list, and its `data' member and its sdata's `string' |
| 1275 | pointer is set to null. The size of the string is recorded in the | 1309 | pointer is set to null. The size of the string is recorded in the |
| 1276 | `u.nbytes' member of the sdata. So, sdata structures that are no | 1310 | `n.nbytes' member of the sdata. So, sdata structures that are no |
| 1277 | longer used, can be easily recognized, and it's easy to compact the | 1311 | longer used, can be easily recognized, and it's easy to compact the |
| 1278 | sblocks of small strings which we do in compact_small_strings. */ | 1312 | sblocks of small strings which we do in compact_small_strings. */ |
| 1279 | 1313 | ||
| @@ -1287,13 +1321,14 @@ mark_interval (register INTERVAL i, Lisp_Object dummy) | |||
| 1287 | 1321 | ||
| 1288 | #define LARGE_STRING_BYTES 1024 | 1322 | #define LARGE_STRING_BYTES 1024 |
| 1289 | 1323 | ||
| 1290 | /* Structure describing string memory sub-allocated from an sblock. | 1324 | /* The SDATA typedef is a struct or union describing string memory |
| 1291 | This is where the contents of Lisp strings are stored. */ | 1325 | sub-allocated from an sblock. This is where the contents of Lisp |
| 1326 | strings are stored. */ | ||
| 1292 | 1327 | ||
| 1293 | struct sdata | 1328 | struct sdata |
| 1294 | { | 1329 | { |
| 1295 | /* Back-pointer to the string this sdata belongs to. If null, this | 1330 | /* Back-pointer to the string this sdata belongs to. If null, this |
| 1296 | structure is free, and the NBYTES member of the union below | 1331 | structure is free, and NBYTES (in this structure or in the union below) |
| 1297 | contains the string's byte size (the same value that STRING_BYTES | 1332 | contains the string's byte size (the same value that STRING_BYTES |
| 1298 | would return if STRING were non-null). If non-null, STRING_BYTES | 1333 | would return if STRING were non-null). If non-null, STRING_BYTES |
| 1299 | (STRING) is the size of the data, and DATA contains the string's | 1334 | (STRING) is the size of the data, and DATA contains the string's |
| @@ -1301,34 +1336,49 @@ struct sdata | |||
| 1301 | struct Lisp_String *string; | 1336 | struct Lisp_String *string; |
| 1302 | 1337 | ||
| 1303 | #ifdef GC_CHECK_STRING_BYTES | 1338 | #ifdef GC_CHECK_STRING_BYTES |
| 1304 | |||
| 1305 | ptrdiff_t nbytes; | 1339 | ptrdiff_t nbytes; |
| 1306 | unsigned char data[1]; | 1340 | #endif |
| 1307 | 1341 | ||
| 1342 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; | ||
| 1343 | }; | ||
| 1344 | |||
| 1345 | #ifdef GC_CHECK_STRING_BYTES | ||
| 1346 | |||
| 1347 | typedef struct sdata sdata; | ||
| 1308 | #define SDATA_NBYTES(S) (S)->nbytes | 1348 | #define SDATA_NBYTES(S) (S)->nbytes |
| 1309 | #define SDATA_DATA(S) (S)->data | 1349 | #define SDATA_DATA(S) (S)->data |
| 1310 | #define SDATA_SELECTOR(member) member | ||
| 1311 | 1350 | ||
| 1312 | #else /* not GC_CHECK_STRING_BYTES */ | 1351 | #else |
| 1313 | 1352 | ||
| 1314 | union | 1353 | typedef union |
| 1315 | { | 1354 | { |
| 1316 | /* When STRING is non-null. */ | 1355 | struct Lisp_String *string; |
| 1317 | unsigned char data[1]; | 1356 | |
| 1357 | /* When STRING is nonnull, this union is actually of type 'struct sdata', | ||
| 1358 | which has a flexible array member. However, if implemented by | ||
| 1359 | giving this union a member of type 'struct sdata', the union | ||
| 1360 | could not be the last (flexible) member of 'struct sblock', | ||
| 1361 | because C99 prohibits a flexible array member from having a type | ||
| 1362 | that is itself a flexible array. So, comment this member out here, | ||
| 1363 | but remember that the option's there when using this union. */ | ||
| 1364 | #if 0 | ||
| 1365 | struct sdata u; | ||
| 1366 | #endif | ||
| 1318 | 1367 | ||
| 1319 | /* When STRING is null. */ | 1368 | /* When STRING is null. */ |
| 1369 | struct | ||
| 1370 | { | ||
| 1371 | struct Lisp_String *string; | ||
| 1320 | ptrdiff_t nbytes; | 1372 | ptrdiff_t nbytes; |
| 1321 | } u; | 1373 | } n; |
| 1374 | } sdata; | ||
| 1322 | 1375 | ||
| 1323 | #define SDATA_NBYTES(S) (S)->u.nbytes | 1376 | #define SDATA_NBYTES(S) (S)->n.nbytes |
| 1324 | #define SDATA_DATA(S) (S)->u.data | 1377 | #define SDATA_DATA(S) ((struct sdata *) (S))->data |
| 1325 | #define SDATA_SELECTOR(member) u.member | ||
| 1326 | 1378 | ||
| 1327 | #endif /* not GC_CHECK_STRING_BYTES */ | 1379 | #endif /* not GC_CHECK_STRING_BYTES */ |
| 1328 | 1380 | ||
| 1329 | #define SDATA_DATA_OFFSET offsetof (struct sdata, SDATA_SELECTOR (data)) | 1381 | enum { SDATA_DATA_OFFSET = offsetof (struct sdata, data) }; |
| 1330 | }; | ||
| 1331 | |||
| 1332 | 1382 | ||
| 1333 | /* Structure describing a block of memory which is sub-allocated to | 1383 | /* Structure describing a block of memory which is sub-allocated to |
| 1334 | obtain string data memory for strings. Blocks for small strings | 1384 | obtain string data memory for strings. Blocks for small strings |
| @@ -1342,10 +1392,10 @@ struct sblock | |||
| 1342 | 1392 | ||
| 1343 | /* Pointer to the next free sdata block. This points past the end | 1393 | /* Pointer to the next free sdata block. This points past the end |
| 1344 | of the sblock if there isn't any space left in this block. */ | 1394 | of the sblock if there isn't any space left in this block. */ |
| 1345 | struct sdata *next_free; | 1395 | sdata *next_free; |
| 1346 | 1396 | ||
| 1347 | /* Start of data. */ | 1397 | /* String data. */ |
| 1348 | struct sdata first_data; | 1398 | sdata data[FLEXIBLE_ARRAY_MEMBER]; |
| 1349 | }; | 1399 | }; |
| 1350 | 1400 | ||
| 1351 | /* Number of Lisp strings in a string_block structure. The 1020 is | 1401 | /* Number of Lisp strings in a string_block structure. The 1020 is |
| @@ -1401,7 +1451,7 @@ static EMACS_INT total_string_bytes; | |||
| 1401 | a pointer to the `u.data' member of its sdata structure; the | 1451 | a pointer to the `u.data' member of its sdata structure; the |
| 1402 | structure starts at a constant offset in front of that. */ | 1452 | structure starts at a constant offset in front of that. */ |
| 1403 | 1453 | ||
| 1404 | #define SDATA_OF_STRING(S) ((struct sdata *) ((S)->data - SDATA_DATA_OFFSET)) | 1454 | #define SDATA_OF_STRING(S) ((sdata *) ((S)->data - SDATA_DATA_OFFSET)) |
| 1405 | 1455 | ||
| 1406 | 1456 | ||
| 1407 | #ifdef GC_CHECK_STRING_OVERRUN | 1457 | #ifdef GC_CHECK_STRING_OVERRUN |
| @@ -1461,7 +1511,7 @@ static ptrdiff_t const STRING_BYTES_MAX = | |||
| 1461 | min (STRING_BYTES_BOUND, | 1511 | min (STRING_BYTES_BOUND, |
| 1462 | ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD | 1512 | ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD |
| 1463 | - GC_STRING_EXTRA | 1513 | - GC_STRING_EXTRA |
| 1464 | - offsetof (struct sblock, first_data) | 1514 | - offsetof (struct sblock, data) |
| 1465 | - SDATA_DATA_OFFSET) | 1515 | - SDATA_DATA_OFFSET) |
| 1466 | & ~(sizeof (EMACS_INT) - 1))); | 1516 | & ~(sizeof (EMACS_INT) - 1))); |
| 1467 | 1517 | ||
| @@ -1500,11 +1550,11 @@ string_bytes (struct Lisp_String *s) | |||
| 1500 | static void | 1550 | static void |
| 1501 | check_sblock (struct sblock *b) | 1551 | check_sblock (struct sblock *b) |
| 1502 | { | 1552 | { |
| 1503 | struct sdata *from, *end, *from_end; | 1553 | sdata *from, *end, *from_end; |
| 1504 | 1554 | ||
| 1505 | end = b->next_free; | 1555 | end = b->next_free; |
| 1506 | 1556 | ||
| 1507 | for (from = &b->first_data; from < end; from = from_end) | 1557 | for (from = b->data; from < end; from = from_end) |
| 1508 | { | 1558 | { |
| 1509 | /* Compute the next FROM here because copying below may | 1559 | /* Compute the next FROM here because copying below may |
| 1510 | overwrite data we need to compute it. */ | 1560 | overwrite data we need to compute it. */ |
| @@ -1514,7 +1564,7 @@ check_sblock (struct sblock *b) | |||
| 1514 | same as the one recorded in the sdata structure. */ | 1564 | same as the one recorded in the sdata structure. */ |
| 1515 | nbytes = SDATA_SIZE (from->string ? string_bytes (from->string) | 1565 | nbytes = SDATA_SIZE (from->string ? string_bytes (from->string) |
| 1516 | : SDATA_NBYTES (from)); | 1566 | : SDATA_NBYTES (from)); |
| 1517 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); | 1567 | from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 1518 | } | 1568 | } |
| 1519 | } | 1569 | } |
| 1520 | 1570 | ||
| @@ -1532,7 +1582,7 @@ check_string_bytes (bool all_p) | |||
| 1532 | 1582 | ||
| 1533 | for (b = large_sblocks; b; b = b->next) | 1583 | for (b = large_sblocks; b; b = b->next) |
| 1534 | { | 1584 | { |
| 1535 | struct Lisp_String *s = b->first_data.string; | 1585 | struct Lisp_String *s = b->data[0].string; |
| 1536 | if (s) | 1586 | if (s) |
| 1537 | string_bytes (s); | 1587 | string_bytes (s); |
| 1538 | } | 1588 | } |
| @@ -1644,7 +1694,7 @@ void | |||
| 1644 | allocate_string_data (struct Lisp_String *s, | 1694 | allocate_string_data (struct Lisp_String *s, |
| 1645 | EMACS_INT nchars, EMACS_INT nbytes) | 1695 | EMACS_INT nchars, EMACS_INT nbytes) |
| 1646 | { | 1696 | { |
| 1647 | struct sdata *data, *old_data; | 1697 | sdata *data, *old_data; |
| 1648 | struct sblock *b; | 1698 | struct sblock *b; |
| 1649 | ptrdiff_t needed, old_nbytes; | 1699 | ptrdiff_t needed, old_nbytes; |
| 1650 | 1700 | ||
| @@ -1666,7 +1716,7 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1666 | 1716 | ||
| 1667 | if (nbytes > LARGE_STRING_BYTES) | 1717 | if (nbytes > LARGE_STRING_BYTES) |
| 1668 | { | 1718 | { |
| 1669 | size_t size = offsetof (struct sblock, first_data) + needed; | 1719 | size_t size = offsetof (struct sblock, data) + needed; |
| 1670 | 1720 | ||
| 1671 | #ifdef DOUG_LEA_MALLOC | 1721 | #ifdef DOUG_LEA_MALLOC |
| 1672 | /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed | 1722 | /* Prevent mmap'ing the chunk. Lisp data may not be mmap'ed |
| @@ -1688,8 +1738,8 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1688 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | 1738 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); |
| 1689 | #endif | 1739 | #endif |
| 1690 | 1740 | ||
| 1691 | b->next_free = &b->first_data; | 1741 | b->next_free = b->data; |
| 1692 | b->first_data.string = NULL; | 1742 | b->data[0].string = NULL; |
| 1693 | b->next = large_sblocks; | 1743 | b->next = large_sblocks; |
| 1694 | large_sblocks = b; | 1744 | large_sblocks = b; |
| 1695 | } | 1745 | } |
| @@ -1700,8 +1750,8 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1700 | { | 1750 | { |
| 1701 | /* Not enough room in the current sblock. */ | 1751 | /* Not enough room in the current sblock. */ |
| 1702 | b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); | 1752 | b = lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); |
| 1703 | b->next_free = &b->first_data; | 1753 | b->next_free = b->data; |
| 1704 | b->first_data.string = NULL; | 1754 | b->data[0].string = NULL; |
| 1705 | b->next = NULL; | 1755 | b->next = NULL; |
| 1706 | 1756 | ||
| 1707 | if (current_sblock) | 1757 | if (current_sblock) |
| @@ -1714,7 +1764,7 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1714 | b = current_sblock; | 1764 | b = current_sblock; |
| 1715 | 1765 | ||
| 1716 | data = b->next_free; | 1766 | data = b->next_free; |
| 1717 | b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); | 1767 | b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA); |
| 1718 | 1768 | ||
| 1719 | MALLOC_UNBLOCK_INPUT; | 1769 | MALLOC_UNBLOCK_INPUT; |
| 1720 | 1770 | ||
| @@ -1785,7 +1835,7 @@ sweep_strings (void) | |||
| 1785 | else | 1835 | else |
| 1786 | { | 1836 | { |
| 1787 | /* String is dead. Put it on the free-list. */ | 1837 | /* String is dead. Put it on the free-list. */ |
| 1788 | struct sdata *data = SDATA_OF_STRING (s); | 1838 | sdata *data = SDATA_OF_STRING (s); |
| 1789 | 1839 | ||
| 1790 | /* Save the size of S in its sdata so that we know | 1840 | /* Save the size of S in its sdata so that we know |
| 1791 | how large that is. Reset the sdata's string | 1841 | how large that is. Reset the sdata's string |
| @@ -1794,7 +1844,7 @@ sweep_strings (void) | |||
| 1794 | if (string_bytes (s) != SDATA_NBYTES (data)) | 1844 | if (string_bytes (s) != SDATA_NBYTES (data)) |
| 1795 | emacs_abort (); | 1845 | emacs_abort (); |
| 1796 | #else | 1846 | #else |
| 1797 | data->u.nbytes = STRING_BYTES (s); | 1847 | data->n.nbytes = STRING_BYTES (s); |
| 1798 | #endif | 1848 | #endif |
| 1799 | data->string = NULL; | 1849 | data->string = NULL; |
| 1800 | 1850 | ||
| @@ -1855,7 +1905,7 @@ free_large_strings (void) | |||
| 1855 | { | 1905 | { |
| 1856 | next = b->next; | 1906 | next = b->next; |
| 1857 | 1907 | ||
| 1858 | if (b->first_data.string == NULL) | 1908 | if (b->data[0].string == NULL) |
| 1859 | lisp_free (b); | 1909 | lisp_free (b); |
| 1860 | else | 1910 | else |
| 1861 | { | 1911 | { |
| @@ -1875,14 +1925,14 @@ static void | |||
| 1875 | compact_small_strings (void) | 1925 | compact_small_strings (void) |
| 1876 | { | 1926 | { |
| 1877 | struct sblock *b, *tb, *next; | 1927 | struct sblock *b, *tb, *next; |
| 1878 | struct sdata *from, *to, *end, *tb_end; | 1928 | sdata *from, *to, *end, *tb_end; |
| 1879 | struct sdata *to_end, *from_end; | 1929 | sdata *to_end, *from_end; |
| 1880 | 1930 | ||
| 1881 | /* TB is the sblock we copy to, TO is the sdata within TB we copy | 1931 | /* TB is the sblock we copy to, TO is the sdata within TB we copy |
| 1882 | to, and TB_END is the end of TB. */ | 1932 | to, and TB_END is the end of TB. */ |
| 1883 | tb = oldest_sblock; | 1933 | tb = oldest_sblock; |
| 1884 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | 1934 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1885 | to = &tb->first_data; | 1935 | to = tb->data; |
| 1886 | 1936 | ||
| 1887 | /* Step through the blocks from the oldest to the youngest. We | 1937 | /* Step through the blocks from the oldest to the youngest. We |
| 1888 | expect that old blocks will stabilize over time, so that less | 1938 | expect that old blocks will stabilize over time, so that less |
| @@ -1892,7 +1942,7 @@ compact_small_strings (void) | |||
| 1892 | end = b->next_free; | 1942 | end = b->next_free; |
| 1893 | eassert ((char *) end <= (char *) b + SBLOCK_SIZE); | 1943 | eassert ((char *) end <= (char *) b + SBLOCK_SIZE); |
| 1894 | 1944 | ||
| 1895 | for (from = &b->first_data; from < end; from = from_end) | 1945 | for (from = b->data; from < end; from = from_end) |
| 1896 | { | 1946 | { |
| 1897 | /* Compute the next FROM here because copying below may | 1947 | /* Compute the next FROM here because copying below may |
| 1898 | overwrite data we need to compute it. */ | 1948 | overwrite data we need to compute it. */ |
| @@ -1910,7 +1960,7 @@ compact_small_strings (void) | |||
| 1910 | eassert (nbytes <= LARGE_STRING_BYTES); | 1960 | eassert (nbytes <= LARGE_STRING_BYTES); |
| 1911 | 1961 | ||
| 1912 | nbytes = SDATA_SIZE (nbytes); | 1962 | nbytes = SDATA_SIZE (nbytes); |
| 1913 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); | 1963 | from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 1914 | 1964 | ||
| 1915 | #ifdef GC_CHECK_STRING_OVERRUN | 1965 | #ifdef GC_CHECK_STRING_OVERRUN |
| 1916 | if (memcmp (string_overrun_cookie, | 1966 | if (memcmp (string_overrun_cookie, |
| @@ -1923,14 +1973,14 @@ compact_small_strings (void) | |||
| 1923 | if (s) | 1973 | if (s) |
| 1924 | { | 1974 | { |
| 1925 | /* If TB is full, proceed with the next sblock. */ | 1975 | /* If TB is full, proceed with the next sblock. */ |
| 1926 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); | 1976 | to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1927 | if (to_end > tb_end) | 1977 | if (to_end > tb_end) |
| 1928 | { | 1978 | { |
| 1929 | tb->next_free = to; | 1979 | tb->next_free = to; |
| 1930 | tb = tb->next; | 1980 | tb = tb->next; |
| 1931 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | 1981 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1932 | to = &tb->first_data; | 1982 | to = tb->data; |
| 1933 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); | 1983 | to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1934 | } | 1984 | } |
| 1935 | 1985 | ||
| 1936 | /* Copy, and update the string's `data' pointer. */ | 1986 | /* Copy, and update the string's `data' pointer. */ |
| @@ -1973,7 +2023,6 @@ INIT must be an integer that represents a character. */) | |||
| 1973 | (Lisp_Object length, Lisp_Object init) | 2023 | (Lisp_Object length, Lisp_Object init) |
| 1974 | { | 2024 | { |
| 1975 | register Lisp_Object val; | 2025 | register Lisp_Object val; |
| 1976 | register unsigned char *p, *end; | ||
| 1977 | int c; | 2026 | int c; |
| 1978 | EMACS_INT nbytes; | 2027 | EMACS_INT nbytes; |
| 1979 | 2028 | ||
| @@ -1985,74 +2034,92 @@ INIT must be an integer that represents a character. */) | |||
| 1985 | { | 2034 | { |
| 1986 | nbytes = XINT (length); | 2035 | nbytes = XINT (length); |
| 1987 | val = make_uninit_string (nbytes); | 2036 | val = make_uninit_string (nbytes); |
| 1988 | p = SDATA (val); | 2037 | memset (SDATA (val), c, nbytes); |
| 1989 | end = p + SCHARS (val); | 2038 | SDATA (val)[nbytes] = 0; |
| 1990 | while (p != end) | ||
| 1991 | *p++ = c; | ||
| 1992 | } | 2039 | } |
| 1993 | else | 2040 | else |
| 1994 | { | 2041 | { |
| 1995 | unsigned char str[MAX_MULTIBYTE_LENGTH]; | 2042 | unsigned char str[MAX_MULTIBYTE_LENGTH]; |
| 1996 | int len = CHAR_STRING (c, str); | 2043 | ptrdiff_t len = CHAR_STRING (c, str); |
| 1997 | EMACS_INT string_len = XINT (length); | 2044 | EMACS_INT string_len = XINT (length); |
| 2045 | unsigned char *p, *beg, *end; | ||
| 1998 | 2046 | ||
| 1999 | if (string_len > STRING_BYTES_MAX / len) | 2047 | if (string_len > STRING_BYTES_MAX / len) |
| 2000 | string_overflow (); | 2048 | string_overflow (); |
| 2001 | nbytes = len * string_len; | 2049 | nbytes = len * string_len; |
| 2002 | val = make_uninit_multibyte_string (string_len, nbytes); | 2050 | val = make_uninit_multibyte_string (string_len, nbytes); |
| 2003 | p = SDATA (val); | 2051 | for (beg = SDATA (val), p = beg, end = beg + nbytes; p < end; p += len) |
| 2004 | end = p + nbytes; | ||
| 2005 | while (p != end) | ||
| 2006 | { | 2052 | { |
| 2007 | memcpy (p, str, len); | 2053 | /* First time we just copy `str' to the data of `val'. */ |
| 2008 | p += len; | 2054 | if (p == beg) |
| 2055 | memcpy (p, str, len); | ||
| 2056 | else | ||
| 2057 | { | ||
| 2058 | /* Next time we copy largest possible chunk from | ||
| 2059 | initialized to uninitialized part of `val'. */ | ||
| 2060 | len = min (p - beg, end - p); | ||
| 2061 | memcpy (p, beg, len); | ||
| 2062 | } | ||
| 2009 | } | 2063 | } |
| 2064 | *p = 0; | ||
| 2010 | } | 2065 | } |
| 2011 | 2066 | ||
| 2012 | *p = 0; | ||
| 2013 | return val; | 2067 | return val; |
| 2014 | } | 2068 | } |
| 2015 | 2069 | ||
| 2070 | /* Fill A with 1 bits if INIT is non-nil, and with 0 bits otherwise. | ||
| 2071 | Return A. */ | ||
| 2016 | 2072 | ||
| 2017 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | 2073 | Lisp_Object |
| 2018 | doc: /* Return a new bool-vector of length LENGTH, using INIT for each element. | 2074 | bool_vector_fill (Lisp_Object a, Lisp_Object init) |
| 2019 | LENGTH must be a number. INIT matters only in whether it is t or nil. */) | ||
| 2020 | (Lisp_Object length, Lisp_Object init) | ||
| 2021 | { | 2075 | { |
| 2022 | register Lisp_Object val; | 2076 | EMACS_INT nbits = bool_vector_size (a); |
| 2023 | struct Lisp_Bool_Vector *p; | 2077 | if (0 < nbits) |
| 2024 | ptrdiff_t length_in_chars; | 2078 | { |
| 2025 | EMACS_INT length_in_elts; | 2079 | unsigned char *data = bool_vector_uchar_data (a); |
| 2026 | int bits_per_value; | 2080 | int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; |
| 2027 | int extra_bool_elts = ((bool_header_size - header_size + word_size - 1) | 2081 | ptrdiff_t nbytes = bool_vector_bytes (nbits); |
| 2028 | / word_size); | 2082 | int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); |
| 2029 | 2083 | memset (data, pattern, nbytes - 1); | |
| 2030 | CHECK_NATNUM (length); | 2084 | data[nbytes - 1] = pattern & last_mask; |
| 2031 | 2085 | } | |
| 2032 | bits_per_value = sizeof (EMACS_INT) * BOOL_VECTOR_BITS_PER_CHAR; | 2086 | return a; |
| 2033 | 2087 | } | |
| 2034 | length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value; | ||
| 2035 | 2088 | ||
| 2036 | val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil); | 2089 | /* Return a newly allocated, uninitialized bool vector of size NBITS. */ |
| 2037 | 2090 | ||
| 2038 | /* No Lisp_Object to trace in there. */ | 2091 | Lisp_Object |
| 2092 | make_uninit_bool_vector (EMACS_INT nbits) | ||
| 2093 | { | ||
| 2094 | Lisp_Object val; | ||
| 2095 | EMACS_INT words = bool_vector_words (nbits); | ||
| 2096 | EMACS_INT word_bytes = words * sizeof (bits_word); | ||
| 2097 | EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes | ||
| 2098 | + word_size - 1) | ||
| 2099 | / word_size); | ||
| 2100 | struct Lisp_Bool_Vector *p | ||
| 2101 | = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); | ||
| 2102 | XSETVECTOR (val, p); | ||
| 2039 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); | 2103 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); |
| 2104 | p->size = nbits; | ||
| 2040 | 2105 | ||
| 2041 | p = XBOOL_VECTOR (val); | 2106 | /* Clear padding at the end. */ |
| 2042 | p->size = XFASTINT (length); | 2107 | if (words) |
| 2108 | p->data[words - 1] = 0; | ||
| 2043 | 2109 | ||
| 2044 | length_in_chars = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1) | 2110 | return val; |
| 2045 | / BOOL_VECTOR_BITS_PER_CHAR); | 2111 | } |
| 2046 | if (length_in_chars) | ||
| 2047 | { | ||
| 2048 | memset (p->data, ! NILP (init) ? -1 : 0, length_in_chars); | ||
| 2049 | 2112 | ||
| 2050 | /* Clear any extraneous bits in the last byte. */ | 2113 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, |
| 2051 | p->data[length_in_chars - 1] | 2114 | doc: /* Return a new bool-vector of length LENGTH, using INIT for each element. |
| 2052 | &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1; | 2115 | LENGTH must be a number. INIT matters only in whether it is t or nil. */) |
| 2053 | } | 2116 | (Lisp_Object length, Lisp_Object init) |
| 2117 | { | ||
| 2118 | Lisp_Object val; | ||
| 2054 | 2119 | ||
| 2055 | return val; | 2120 | CHECK_NATNUM (length); |
| 2121 | val = make_uninit_bool_vector (XFASTINT (length)); | ||
| 2122 | return bool_vector_fill (val, init); | ||
| 2056 | } | 2123 | } |
| 2057 | 2124 | ||
| 2058 | 2125 | ||
| @@ -2565,36 +2632,53 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, | |||
| 2565 | Vector Allocation | 2632 | Vector Allocation |
| 2566 | ***********************************************************************/ | 2633 | ***********************************************************************/ |
| 2567 | 2634 | ||
| 2635 | /* Sometimes a vector's contents are merely a pointer internally used | ||
| 2636 | in vector allocation code. Usually you don't want to touch this. */ | ||
| 2637 | |||
| 2638 | static struct Lisp_Vector * | ||
| 2639 | next_vector (struct Lisp_Vector *v) | ||
| 2640 | { | ||
| 2641 | return XUNTAG (v->contents[0], 0); | ||
| 2642 | } | ||
| 2643 | |||
| 2644 | static void | ||
| 2645 | set_next_vector (struct Lisp_Vector *v, struct Lisp_Vector *p) | ||
| 2646 | { | ||
| 2647 | v->contents[0] = make_lisp_ptr (p, 0); | ||
| 2648 | } | ||
| 2649 | |||
| 2568 | /* This value is balanced well enough to avoid too much internal overhead | 2650 | /* This value is balanced well enough to avoid too much internal overhead |
| 2569 | for the most common cases; it's not required to be a power of two, but | 2651 | for the most common cases; it's not required to be a power of two, but |
| 2570 | it's expected to be a mult-of-ROUNDUP_SIZE (see below). */ | 2652 | it's expected to be a mult-of-ROUNDUP_SIZE (see below). */ |
| 2571 | 2653 | ||
| 2572 | #define VECTOR_BLOCK_SIZE 4096 | 2654 | #define VECTOR_BLOCK_SIZE 4096 |
| 2573 | 2655 | ||
| 2574 | /* Align allocation request sizes to be a multiple of ROUNDUP_SIZE. */ | ||
| 2575 | enum | 2656 | enum |
| 2576 | { | 2657 | { |
| 2577 | roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? GCALIGNMENT : 1) | 2658 | /* Alignment of struct Lisp_Vector objects. */ |
| 2578 | }; | 2659 | vector_alignment = COMMON_MULTIPLE (ALIGNOF_STRUCT_LISP_VECTOR, |
| 2660 | USE_LSB_TAG ? GCALIGNMENT : 1), | ||
| 2579 | 2661 | ||
| 2580 | /* ROUNDUP_SIZE must be a power of 2. */ | 2662 | /* Vector size requests are a multiple of this. */ |
| 2581 | verify ((roundup_size & (roundup_size - 1)) == 0); | 2663 | roundup_size = COMMON_MULTIPLE (vector_alignment, word_size) |
| 2664 | }; | ||
| 2582 | 2665 | ||
| 2583 | /* Verify assumptions described above. */ | 2666 | /* Verify assumptions described above. */ |
| 2584 | verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); | 2667 | verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); |
| 2585 | verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | 2668 | verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); |
| 2586 | 2669 | ||
| 2587 | /* Round up X to nearest mult-of-ROUNDUP_SIZE. */ | 2670 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */ |
| 2588 | 2671 | #define vroundup_ct(x) ROUNDUP (x, roundup_size) | |
| 2589 | #define vroundup(x) (((x) + (roundup_size - 1)) & ~(roundup_size - 1)) | 2672 | /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */ |
| 2673 | #define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x)) | ||
| 2590 | 2674 | ||
| 2591 | /* Rounding helps to maintain alignment constraints if USE_LSB_TAG. */ | 2675 | /* Rounding helps to maintain alignment constraints if USE_LSB_TAG. */ |
| 2592 | 2676 | ||
| 2593 | #define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup (sizeof (void *))) | 2677 | #define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *))) |
| 2594 | 2678 | ||
| 2595 | /* Size of the minimal vector allocated from block. */ | 2679 | /* Size of the minimal vector allocated from block. */ |
| 2596 | 2680 | ||
| 2597 | #define VBLOCK_BYTES_MIN vroundup (sizeof (struct Lisp_Vector)) | 2681 | #define VBLOCK_BYTES_MIN vroundup_ct (header_size + sizeof (Lisp_Object)) |
| 2598 | 2682 | ||
| 2599 | /* Size of the largest vector allocated from block. */ | 2683 | /* Size of the largest vector allocated from block. */ |
| 2600 | 2684 | ||
| @@ -2615,22 +2699,6 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | |||
| 2615 | 2699 | ||
| 2616 | #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size) | 2700 | #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size) |
| 2617 | 2701 | ||
| 2618 | /* Get and set the next field in block-allocated vectorlike objects on | ||
| 2619 | the free list. Doing it this way respects C's aliasing rules. | ||
| 2620 | We could instead make 'contents' a union, but that would mean | ||
| 2621 | changes everywhere that the code uses 'contents'. */ | ||
| 2622 | static struct Lisp_Vector * | ||
| 2623 | next_in_free_list (struct Lisp_Vector *v) | ||
| 2624 | { | ||
| 2625 | intptr_t i = XLI (v->contents[0]); | ||
| 2626 | return (struct Lisp_Vector *) i; | ||
| 2627 | } | ||
| 2628 | static void | ||
| 2629 | set_next_in_free_list (struct Lisp_Vector *v, struct Lisp_Vector *next) | ||
| 2630 | { | ||
| 2631 | v->contents[0] = XIL ((intptr_t) next); | ||
| 2632 | } | ||
| 2633 | |||
| 2634 | /* Common shortcut to setup vector on a free list. */ | 2702 | /* Common shortcut to setup vector on a free list. */ |
| 2635 | 2703 | ||
| 2636 | #define SETUP_ON_FREE_LIST(v, nbytes, tmp) \ | 2704 | #define SETUP_ON_FREE_LIST(v, nbytes, tmp) \ |
| @@ -2640,26 +2708,37 @@ set_next_in_free_list (struct Lisp_Vector *v, struct Lisp_Vector *next) | |||
| 2640 | eassert ((nbytes) % roundup_size == 0); \ | 2708 | eassert ((nbytes) % roundup_size == 0); \ |
| 2641 | (tmp) = VINDEX (nbytes); \ | 2709 | (tmp) = VINDEX (nbytes); \ |
| 2642 | eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \ | 2710 | eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \ |
| 2643 | set_next_in_free_list (v, vector_free_lists[tmp]); \ | 2711 | set_next_vector (v, vector_free_lists[tmp]); \ |
| 2644 | vector_free_lists[tmp] = (v); \ | 2712 | vector_free_lists[tmp] = (v); \ |
| 2645 | total_free_vector_slots += (nbytes) / word_size; \ | 2713 | total_free_vector_slots += (nbytes) / word_size; \ |
| 2646 | } while (0) | 2714 | } while (0) |
| 2647 | 2715 | ||
| 2648 | /* This internal type is used to maintain the list of large vectors | 2716 | /* This internal type is used to maintain the list of large vectors |
| 2649 | which are allocated at their own, e.g. outside of vector blocks. */ | 2717 | which are allocated at their own, e.g. outside of vector blocks. |
| 2718 | |||
| 2719 | struct large_vector itself cannot contain a struct Lisp_Vector, as | ||
| 2720 | the latter contains a flexible array member and C99 does not allow | ||
| 2721 | such structs to be nested. Instead, each struct large_vector | ||
| 2722 | object LV is followed by a struct Lisp_Vector, which is at offset | ||
| 2723 | large_vector_offset from LV, and whose address is therefore | ||
| 2724 | large_vector_vec (&LV). */ | ||
| 2650 | 2725 | ||
| 2651 | struct large_vector | 2726 | struct large_vector |
| 2652 | { | 2727 | { |
| 2653 | union { | 2728 | struct large_vector *next; |
| 2654 | struct large_vector *vector; | 2729 | }; |
| 2655 | #if USE_LSB_TAG | 2730 | |
| 2656 | /* We need to maintain ROUNDUP_SIZE alignment for the vector member. */ | 2731 | enum |
| 2657 | unsigned char c[vroundup (sizeof (struct large_vector *))]; | 2732 | { |
| 2658 | #endif | 2733 | large_vector_offset = ROUNDUP (sizeof (struct large_vector), vector_alignment) |
| 2659 | } next; | ||
| 2660 | struct Lisp_Vector v; | ||
| 2661 | }; | 2734 | }; |
| 2662 | 2735 | ||
| 2736 | static struct Lisp_Vector * | ||
| 2737 | large_vector_vec (struct large_vector *p) | ||
| 2738 | { | ||
| 2739 | return (struct Lisp_Vector *) ((char *) p + large_vector_offset); | ||
| 2740 | } | ||
| 2741 | |||
| 2663 | /* This internal type is used to maintain an underlying storage | 2742 | /* This internal type is used to maintain an underlying storage |
| 2664 | for small vectors. */ | 2743 | for small vectors. */ |
| 2665 | 2744 | ||
| @@ -2737,7 +2816,7 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2737 | if (vector_free_lists[index]) | 2816 | if (vector_free_lists[index]) |
| 2738 | { | 2817 | { |
| 2739 | vector = vector_free_lists[index]; | 2818 | vector = vector_free_lists[index]; |
| 2740 | vector_free_lists[index] = next_in_free_list (vector); | 2819 | vector_free_lists[index] = next_vector (vector); |
| 2741 | total_free_vector_slots -= nbytes / word_size; | 2820 | total_free_vector_slots -= nbytes / word_size; |
| 2742 | return vector; | 2821 | return vector; |
| 2743 | } | 2822 | } |
| @@ -2751,7 +2830,7 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2751 | { | 2830 | { |
| 2752 | /* This vector is larger than requested. */ | 2831 | /* This vector is larger than requested. */ |
| 2753 | vector = vector_free_lists[index]; | 2832 | vector = vector_free_lists[index]; |
| 2754 | vector_free_lists[index] = next_in_free_list (vector); | 2833 | vector_free_lists[index] = next_vector (vector); |
| 2755 | total_free_vector_slots -= nbytes / word_size; | 2834 | total_free_vector_slots -= nbytes / word_size; |
| 2756 | 2835 | ||
| 2757 | /* Excess bytes are used for the smaller vector, | 2836 | /* Excess bytes are used for the smaller vector, |
| @@ -2791,23 +2870,44 @@ static ptrdiff_t | |||
| 2791 | vector_nbytes (struct Lisp_Vector *v) | 2870 | vector_nbytes (struct Lisp_Vector *v) |
| 2792 | { | 2871 | { |
| 2793 | ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; | 2872 | ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; |
| 2873 | ptrdiff_t nwords; | ||
| 2794 | 2874 | ||
| 2795 | if (size & PSEUDOVECTOR_FLAG) | 2875 | if (size & PSEUDOVECTOR_FLAG) |
| 2796 | { | 2876 | { |
| 2797 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) | 2877 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) |
| 2798 | size = (bool_header_size | 2878 | { |
| 2799 | + (((struct Lisp_Bool_Vector *) v)->size | 2879 | struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; |
| 2800 | + BOOL_VECTOR_BITS_PER_CHAR - 1) | 2880 | ptrdiff_t word_bytes = (bool_vector_words (bv->size) |
| 2801 | / BOOL_VECTOR_BITS_PER_CHAR); | 2881 | * sizeof (bits_word)); |
| 2882 | ptrdiff_t boolvec_bytes = bool_header_size + word_bytes; | ||
| 2883 | verify (header_size <= bool_header_size); | ||
| 2884 | nwords = (boolvec_bytes - header_size + word_size - 1) / word_size; | ||
| 2885 | } | ||
| 2802 | else | 2886 | else |
| 2803 | size = (header_size | 2887 | nwords = ((size & PSEUDOVECTOR_SIZE_MASK) |
| 2804 | + ((size & PSEUDOVECTOR_SIZE_MASK) | 2888 | + ((size & PSEUDOVECTOR_REST_MASK) |
| 2805 | + ((size & PSEUDOVECTOR_REST_MASK) | 2889 | >> PSEUDOVECTOR_SIZE_BITS)); |
| 2806 | >> PSEUDOVECTOR_SIZE_BITS)) * word_size); | ||
| 2807 | } | 2890 | } |
| 2808 | else | 2891 | else |
| 2809 | size = header_size + size * word_size; | 2892 | nwords = size; |
| 2810 | return vroundup (size); | 2893 | return vroundup (header_size + word_size * nwords); |
| 2894 | } | ||
| 2895 | |||
| 2896 | /* Release extra resources still in use by VECTOR, which may be any | ||
| 2897 | vector-like object. For now, this is used just to free data in | ||
| 2898 | font objects. */ | ||
| 2899 | |||
| 2900 | static void | ||
| 2901 | cleanup_vector (struct Lisp_Vector *vector) | ||
| 2902 | { | ||
| 2903 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT) | ||
| 2904 | && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) | ||
| 2905 | == FONT_OBJECT_MAX)) | ||
| 2906 | { | ||
| 2907 | /* Attempt to catch subtle bugs like Bug#16140. */ | ||
| 2908 | eassert (valid_font_driver (((struct font *) vector)->driver)); | ||
| 2909 | ((struct font *) vector)->driver->close ((struct font *) vector); | ||
| 2910 | } | ||
| 2811 | } | 2911 | } |
| 2812 | 2912 | ||
| 2813 | /* Reclaim space used by unmarked vectors. */ | 2913 | /* Reclaim space used by unmarked vectors. */ |
| @@ -2815,7 +2915,7 @@ vector_nbytes (struct Lisp_Vector *v) | |||
| 2815 | static void | 2915 | static void |
| 2816 | sweep_vectors (void) | 2916 | sweep_vectors (void) |
| 2817 | { | 2917 | { |
| 2818 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; | 2918 | struct vector_block *block, **bprev = &vector_blocks; |
| 2819 | struct large_vector *lv, **lvprev = &large_vectors; | 2919 | struct large_vector *lv, **lvprev = &large_vectors; |
| 2820 | struct Lisp_Vector *vector, *next; | 2920 | struct Lisp_Vector *vector, *next; |
| 2821 | 2921 | ||
| @@ -2844,6 +2944,7 @@ sweep_vectors (void) | |||
| 2844 | { | 2944 | { |
| 2845 | ptrdiff_t total_bytes; | 2945 | ptrdiff_t total_bytes; |
| 2846 | 2946 | ||
| 2947 | cleanup_vector (vector); | ||
| 2847 | nbytes = vector_nbytes (vector); | 2948 | nbytes = vector_nbytes (vector); |
| 2848 | total_bytes = nbytes; | 2949 | total_bytes = nbytes; |
| 2849 | next = ADVANCE (vector, nbytes); | 2950 | next = ADVANCE (vector, nbytes); |
| @@ -2855,6 +2956,7 @@ sweep_vectors (void) | |||
| 2855 | { | 2956 | { |
| 2856 | if (VECTOR_MARKED_P (next)) | 2957 | if (VECTOR_MARKED_P (next)) |
| 2857 | break; | 2958 | break; |
| 2959 | cleanup_vector (next); | ||
| 2858 | nbytes = vector_nbytes (next); | 2960 | nbytes = vector_nbytes (next); |
| 2859 | total_bytes += nbytes; | 2961 | total_bytes += nbytes; |
| 2860 | next = ADVANCE (next, nbytes); | 2962 | next = ADVANCE (next, nbytes); |
| @@ -2869,7 +2971,7 @@ sweep_vectors (void) | |||
| 2869 | free_this_block = 1; | 2971 | free_this_block = 1; |
| 2870 | else | 2972 | else |
| 2871 | { | 2973 | { |
| 2872 | int tmp; | 2974 | size_t tmp; |
| 2873 | SETUP_ON_FREE_LIST (vector, total_bytes, tmp); | 2975 | SETUP_ON_FREE_LIST (vector, total_bytes, tmp); |
| 2874 | } | 2976 | } |
| 2875 | } | 2977 | } |
| @@ -2891,33 +2993,27 @@ sweep_vectors (void) | |||
| 2891 | 2993 | ||
| 2892 | for (lv = large_vectors; lv; lv = *lvprev) | 2994 | for (lv = large_vectors; lv; lv = *lvprev) |
| 2893 | { | 2995 | { |
| 2894 | vector = &lv->v; | 2996 | vector = large_vector_vec (lv); |
| 2895 | if (VECTOR_MARKED_P (vector)) | 2997 | if (VECTOR_MARKED_P (vector)) |
| 2896 | { | 2998 | { |
| 2897 | VECTOR_UNMARK (vector); | 2999 | VECTOR_UNMARK (vector); |
| 2898 | total_vectors++; | 3000 | total_vectors++; |
| 2899 | if (vector->header.size & PSEUDOVECTOR_FLAG) | 3001 | if (vector->header.size & PSEUDOVECTOR_FLAG) |
| 2900 | { | 3002 | { |
| 2901 | struct Lisp_Bool_Vector *b = (struct Lisp_Bool_Vector *) vector; | ||
| 2902 | |||
| 2903 | /* All non-bool pseudovectors are small enough to be allocated | 3003 | /* All non-bool pseudovectors are small enough to be allocated |
| 2904 | from vector blocks. This code should be redesigned if some | 3004 | from vector blocks. This code should be redesigned if some |
| 2905 | pseudovector type grows beyond VBLOCK_BYTES_MAX. */ | 3005 | pseudovector type grows beyond VBLOCK_BYTES_MAX. */ |
| 2906 | eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)); | 3006 | eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)); |
| 2907 | 3007 | total_vector_slots += vector_nbytes (vector) / word_size; | |
| 2908 | total_vector_slots | ||
| 2909 | += (bool_header_size | ||
| 2910 | + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1) | ||
| 2911 | / BOOL_VECTOR_BITS_PER_CHAR)) / word_size; | ||
| 2912 | } | 3008 | } |
| 2913 | else | 3009 | else |
| 2914 | total_vector_slots | 3010 | total_vector_slots |
| 2915 | += header_size / word_size + vector->header.size; | 3011 | += header_size / word_size + vector->header.size; |
| 2916 | lvprev = &lv->next.vector; | 3012 | lvprev = &lv->next; |
| 2917 | } | 3013 | } |
| 2918 | else | 3014 | else |
| 2919 | { | 3015 | { |
| 2920 | *lvprev = lv->next.vector; | 3016 | *lvprev = lv->next; |
| 2921 | lisp_free (lv); | 3017 | lisp_free (lv); |
| 2922 | } | 3018 | } |
| 2923 | } | 3019 | } |
| @@ -2951,11 +3047,12 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 2951 | else | 3047 | else |
| 2952 | { | 3048 | { |
| 2953 | struct large_vector *lv | 3049 | struct large_vector *lv |
| 2954 | = lisp_malloc (sizeof (*lv) + (len - 1) * word_size, | 3050 | = lisp_malloc ((large_vector_offset + header_size |
| 3051 | + len * word_size), | ||
| 2955 | MEM_TYPE_VECTORLIKE); | 3052 | MEM_TYPE_VECTORLIKE); |
| 2956 | lv->next.vector = large_vectors; | 3053 | lv->next = large_vectors; |
| 2957 | large_vectors = lv; | 3054 | large_vectors = lv; |
| 2958 | p = &lv->v; | 3055 | p = large_vector_vec (lv); |
| 2959 | } | 3056 | } |
| 2960 | 3057 | ||
| 2961 | #ifdef DOUG_LEA_MALLOC | 3058 | #ifdef DOUG_LEA_MALLOC |
| @@ -3117,6 +3214,9 @@ usage: (vector &rest OBJECTS) */) | |||
| 3117 | void | 3214 | void |
| 3118 | make_byte_code (struct Lisp_Vector *v) | 3215 | make_byte_code (struct Lisp_Vector *v) |
| 3119 | { | 3216 | { |
| 3217 | /* Don't allow the global zero_vector to become a byte code object. */ | ||
| 3218 | eassert (0 < v->header.size); | ||
| 3219 | |||
| 3120 | if (v->header.size > 1 && STRINGP (v->contents[1]) | 3220 | if (v->header.size > 1 && STRINGP (v->contents[1]) |
| 3121 | && STRING_MULTIBYTE (v->contents[1])) | 3221 | && STRING_MULTIBYTE (v->contents[1])) |
| 3122 | /* BYTECODE-STRING must have been produced by Emacs 20.2 or the | 3222 | /* BYTECODE-STRING must have been produced by Emacs 20.2 or the |
| @@ -3207,6 +3307,12 @@ static int symbol_block_index = SYMBOL_BLOCK_SIZE; | |||
| 3207 | 3307 | ||
| 3208 | static struct Lisp_Symbol *symbol_free_list; | 3308 | static struct Lisp_Symbol *symbol_free_list; |
| 3209 | 3309 | ||
| 3310 | static void | ||
| 3311 | set_symbol_name (Lisp_Object sym, Lisp_Object name) | ||
| 3312 | { | ||
| 3313 | XSYMBOL (sym)->name = name; | ||
| 3314 | } | ||
| 3315 | |||
| 3210 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, | 3316 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, |
| 3211 | doc: /* Return a newly allocated uninterned symbol whose name is NAME. | 3317 | doc: /* Return a newly allocated uninterned symbol whose name is NAME. |
| 3212 | Its value is void, and its function definition and property list are nil. */) | 3318 | Its value is void, and its function definition and property list are nil. */) |
| @@ -3327,7 +3433,7 @@ allocate_misc (enum Lisp_Misc_Type type) | |||
| 3327 | --total_free_markers; | 3433 | --total_free_markers; |
| 3328 | consing_since_gc += sizeof (union Lisp_Misc); | 3434 | consing_since_gc += sizeof (union Lisp_Misc); |
| 3329 | misc_objects_consed++; | 3435 | misc_objects_consed++; |
| 3330 | XMISCTYPE (val) = type; | 3436 | XMISCANY (val)->type = type; |
| 3331 | XMISCANY (val)->gcmarkbit = 0; | 3437 | XMISCANY (val)->gcmarkbit = 0; |
| 3332 | return val; | 3438 | return val; |
| 3333 | } | 3439 | } |
| @@ -3337,85 +3443,114 @@ allocate_misc (enum Lisp_Misc_Type type) | |||
| 3337 | void | 3443 | void |
| 3338 | free_misc (Lisp_Object misc) | 3444 | free_misc (Lisp_Object misc) |
| 3339 | { | 3445 | { |
| 3340 | XMISCTYPE (misc) = Lisp_Misc_Free; | 3446 | XMISCANY (misc)->type = Lisp_Misc_Free; |
| 3341 | XMISC (misc)->u_free.chain = marker_free_list; | 3447 | XMISC (misc)->u_free.chain = marker_free_list; |
| 3342 | marker_free_list = XMISC (misc); | 3448 | marker_free_list = XMISC (misc); |
| 3343 | consing_since_gc -= sizeof (union Lisp_Misc); | 3449 | consing_since_gc -= sizeof (union Lisp_Misc); |
| 3344 | total_free_markers++; | 3450 | total_free_markers++; |
| 3345 | } | 3451 | } |
| 3346 | 3452 | ||
| 3347 | /* Return a Lisp_Save_Value object with the data saved according to | 3453 | /* Verify properties of Lisp_Save_Value's representation |
| 3348 | FMT. Format specifiers are `i' for an integer, `p' for a pointer | 3454 | that are assumed here and elsewhere. */ |
| 3349 | and `o' for Lisp_Object. Up to 4 objects can be specified. */ | 3455 | |
| 3456 | verify (SAVE_UNUSED == 0); | ||
| 3457 | verify (((SAVE_INTEGER | SAVE_POINTER | SAVE_FUNCPOINTER | SAVE_OBJECT) | ||
| 3458 | >> SAVE_SLOT_BITS) | ||
| 3459 | == 0); | ||
| 3460 | |||
| 3461 | /* Return Lisp_Save_Value objects for the various combinations | ||
| 3462 | that callers need. */ | ||
| 3350 | 3463 | ||
| 3351 | Lisp_Object | 3464 | Lisp_Object |
| 3352 | make_save_value (const char *fmt, ...) | 3465 | make_save_int_int_int (ptrdiff_t a, ptrdiff_t b, ptrdiff_t c) |
| 3353 | { | 3466 | { |
| 3354 | va_list ap; | ||
| 3355 | int len = strlen (fmt); | ||
| 3356 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | 3467 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); |
| 3357 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | 3468 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); |
| 3469 | p->save_type = SAVE_TYPE_INT_INT_INT; | ||
| 3470 | p->data[0].integer = a; | ||
| 3471 | p->data[1].integer = b; | ||
| 3472 | p->data[2].integer = c; | ||
| 3473 | return val; | ||
| 3474 | } | ||
| 3358 | 3475 | ||
| 3359 | eassert (0 < len && len < 5); | 3476 | Lisp_Object |
| 3360 | va_start (ap, fmt); | 3477 | make_save_obj_obj_obj_obj (Lisp_Object a, Lisp_Object b, Lisp_Object c, |
| 3361 | 3478 | Lisp_Object d) | |
| 3362 | #define INITX(index) \ | 3479 | { |
| 3363 | do { \ | 3480 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); |
| 3364 | if (len <= index) \ | 3481 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); |
| 3365 | p->type ## index = SAVE_UNUSED; \ | 3482 | p->save_type = SAVE_TYPE_OBJ_OBJ_OBJ_OBJ; |
| 3366 | else \ | 3483 | p->data[0].object = a; |
| 3367 | { \ | 3484 | p->data[1].object = b; |
| 3368 | if (fmt[index] == 'i') \ | 3485 | p->data[2].object = c; |
| 3369 | { \ | 3486 | p->data[3].object = d; |
| 3370 | p->type ## index = SAVE_INTEGER; \ | 3487 | return val; |
| 3371 | p->data[index].integer = va_arg (ap, ptrdiff_t); \ | 3488 | } |
| 3372 | } \ | ||
| 3373 | else if (fmt[index] == 'p') \ | ||
| 3374 | { \ | ||
| 3375 | p->type ## index = SAVE_POINTER; \ | ||
| 3376 | p->data[index].pointer = va_arg (ap, void *); \ | ||
| 3377 | } \ | ||
| 3378 | else if (fmt[index] == 'o') \ | ||
| 3379 | { \ | ||
| 3380 | p->type ## index = SAVE_OBJECT; \ | ||
| 3381 | p->data[index].object = va_arg (ap, Lisp_Object); \ | ||
| 3382 | } \ | ||
| 3383 | else \ | ||
| 3384 | emacs_abort (); \ | ||
| 3385 | } \ | ||
| 3386 | } while (0) | ||
| 3387 | |||
| 3388 | INITX (0); | ||
| 3389 | INITX (1); | ||
| 3390 | INITX (2); | ||
| 3391 | INITX (3); | ||
| 3392 | 3489 | ||
| 3393 | #undef INITX | 3490 | Lisp_Object |
| 3491 | make_save_ptr (void *a) | ||
| 3492 | { | ||
| 3493 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | ||
| 3494 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | ||
| 3495 | p->save_type = SAVE_POINTER; | ||
| 3496 | p->data[0].pointer = a; | ||
| 3497 | return val; | ||
| 3498 | } | ||
| 3394 | 3499 | ||
| 3395 | va_end (ap); | 3500 | Lisp_Object |
| 3396 | p->area = 0; | 3501 | make_save_ptr_int (void *a, ptrdiff_t b) |
| 3502 | { | ||
| 3503 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | ||
| 3504 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | ||
| 3505 | p->save_type = SAVE_TYPE_PTR_INT; | ||
| 3506 | p->data[0].pointer = a; | ||
| 3507 | p->data[1].integer = b; | ||
| 3397 | return val; | 3508 | return val; |
| 3398 | } | 3509 | } |
| 3399 | 3510 | ||
| 3400 | /* The most common task it to save just one C pointer. */ | 3511 | #if ! (defined USE_X_TOOLKIT || defined USE_GTK) |
| 3512 | Lisp_Object | ||
| 3513 | make_save_ptr_ptr (void *a, void *b) | ||
| 3514 | { | ||
| 3515 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | ||
| 3516 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | ||
| 3517 | p->save_type = SAVE_TYPE_PTR_PTR; | ||
| 3518 | p->data[0].pointer = a; | ||
| 3519 | p->data[1].pointer = b; | ||
| 3520 | return val; | ||
| 3521 | } | ||
| 3522 | #endif | ||
| 3401 | 3523 | ||
| 3402 | Lisp_Object | 3524 | Lisp_Object |
| 3403 | make_save_pointer (void *pointer) | 3525 | make_save_funcptr_ptr_obj (void (*a) (void), void *b, Lisp_Object c) |
| 3404 | { | 3526 | { |
| 3405 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | 3527 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); |
| 3406 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | 3528 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); |
| 3529 | p->save_type = SAVE_TYPE_FUNCPTR_PTR_OBJ; | ||
| 3530 | p->data[0].funcpointer = a; | ||
| 3531 | p->data[1].pointer = b; | ||
| 3532 | p->data[2].object = c; | ||
| 3533 | return val; | ||
| 3534 | } | ||
| 3407 | 3535 | ||
| 3408 | p->area = 0; | 3536 | /* Return a Lisp_Save_Value object that represents an array A |
| 3409 | p->type0 = SAVE_POINTER; | 3537 | of N Lisp objects. */ |
| 3410 | p->data[0].pointer = pointer; | 3538 | |
| 3411 | p->type1 = p->type2 = p->type3 = SAVE_UNUSED; | 3539 | Lisp_Object |
| 3540 | make_save_memory (Lisp_Object *a, ptrdiff_t n) | ||
| 3541 | { | ||
| 3542 | Lisp_Object val = allocate_misc (Lisp_Misc_Save_Value); | ||
| 3543 | struct Lisp_Save_Value *p = XSAVE_VALUE (val); | ||
| 3544 | p->save_type = SAVE_TYPE_MEMORY; | ||
| 3545 | p->data[0].pointer = a; | ||
| 3546 | p->data[1].integer = n; | ||
| 3412 | return val; | 3547 | return val; |
| 3413 | } | 3548 | } |
| 3414 | 3549 | ||
| 3415 | /* Free a Lisp_Save_Value object. Do not use this function | 3550 | /* Free a Lisp_Save_Value object. Do not use this function |
| 3416 | if SAVE contains pointer other than returned by xmalloc. */ | 3551 | if SAVE contains pointer other than returned by xmalloc. */ |
| 3417 | 3552 | ||
| 3418 | static void | 3553 | void |
| 3419 | free_save_value (Lisp_Object save) | 3554 | free_save_value (Lisp_Object save) |
| 3420 | { | 3555 | { |
| 3421 | xfree (XSAVE_POINTER (save, 0)); | 3556 | xfree (XSAVE_POINTER (save, 0)); |
| @@ -3451,6 +3586,7 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, | |||
| 3451 | p->charpos = 0; | 3586 | p->charpos = 0; |
| 3452 | p->next = NULL; | 3587 | p->next = NULL; |
| 3453 | p->insertion_type = 0; | 3588 | p->insertion_type = 0; |
| 3589 | p->need_adjustment = 0; | ||
| 3454 | return val; | 3590 | return val; |
| 3455 | } | 3591 | } |
| 3456 | 3592 | ||
| @@ -3475,6 +3611,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) | |||
| 3475 | m->charpos = charpos; | 3611 | m->charpos = charpos; |
| 3476 | m->bytepos = bytepos; | 3612 | m->bytepos = bytepos; |
| 3477 | m->insertion_type = 0; | 3613 | m->insertion_type = 0; |
| 3614 | m->need_adjustment = 0; | ||
| 3478 | m->next = BUF_MARKERS (buf); | 3615 | m->next = BUF_MARKERS (buf); |
| 3479 | BUF_MARKERS (buf) = m; | 3616 | BUF_MARKERS (buf) = m; |
| 3480 | return obj; | 3617 | return obj; |
| @@ -3497,9 +3634,9 @@ free_marker (Lisp_Object marker) | |||
| 3497 | Any number of arguments, even zero arguments, are allowed. */ | 3634 | Any number of arguments, even zero arguments, are allowed. */ |
| 3498 | 3635 | ||
| 3499 | Lisp_Object | 3636 | Lisp_Object |
| 3500 | make_event_array (register int nargs, Lisp_Object *args) | 3637 | make_event_array (ptrdiff_t nargs, Lisp_Object *args) |
| 3501 | { | 3638 | { |
| 3502 | int i; | 3639 | ptrdiff_t i; |
| 3503 | 3640 | ||
| 3504 | for (i = 0; i < nargs; i++) | 3641 | for (i = 0; i < nargs; i++) |
| 3505 | /* The things that fit in a string | 3642 | /* The things that fit in a string |
| @@ -4037,7 +4174,7 @@ live_string_p (struct mem_node *m, void *p) | |||
| 4037 | { | 4174 | { |
| 4038 | if (m->type == MEM_TYPE_STRING) | 4175 | if (m->type == MEM_TYPE_STRING) |
| 4039 | { | 4176 | { |
| 4040 | struct string_block *b = (struct string_block *) m->start; | 4177 | struct string_block *b = m->start; |
| 4041 | ptrdiff_t offset = (char *) p - (char *) &b->strings[0]; | 4178 | ptrdiff_t offset = (char *) p - (char *) &b->strings[0]; |
| 4042 | 4179 | ||
| 4043 | /* P must point to the start of a Lisp_String structure, and it | 4180 | /* P must point to the start of a Lisp_String structure, and it |
| @@ -4060,7 +4197,7 @@ live_cons_p (struct mem_node *m, void *p) | |||
| 4060 | { | 4197 | { |
| 4061 | if (m->type == MEM_TYPE_CONS) | 4198 | if (m->type == MEM_TYPE_CONS) |
| 4062 | { | 4199 | { |
| 4063 | struct cons_block *b = (struct cons_block *) m->start; | 4200 | struct cons_block *b = m->start; |
| 4064 | ptrdiff_t offset = (char *) p - (char *) &b->conses[0]; | 4201 | ptrdiff_t offset = (char *) p - (char *) &b->conses[0]; |
| 4065 | 4202 | ||
| 4066 | /* P must point to the start of a Lisp_Cons, not be | 4203 | /* P must point to the start of a Lisp_Cons, not be |
| @@ -4086,7 +4223,7 @@ live_symbol_p (struct mem_node *m, void *p) | |||
| 4086 | { | 4223 | { |
| 4087 | if (m->type == MEM_TYPE_SYMBOL) | 4224 | if (m->type == MEM_TYPE_SYMBOL) |
| 4088 | { | 4225 | { |
| 4089 | struct symbol_block *b = (struct symbol_block *) m->start; | 4226 | struct symbol_block *b = m->start; |
| 4090 | ptrdiff_t offset = (char *) p - (char *) &b->symbols[0]; | 4227 | ptrdiff_t offset = (char *) p - (char *) &b->symbols[0]; |
| 4091 | 4228 | ||
| 4092 | /* P must point to the start of a Lisp_Symbol, not be | 4229 | /* P must point to the start of a Lisp_Symbol, not be |
| @@ -4112,7 +4249,7 @@ live_float_p (struct mem_node *m, void *p) | |||
| 4112 | { | 4249 | { |
| 4113 | if (m->type == MEM_TYPE_FLOAT) | 4250 | if (m->type == MEM_TYPE_FLOAT) |
| 4114 | { | 4251 | { |
| 4115 | struct float_block *b = (struct float_block *) m->start; | 4252 | struct float_block *b = m->start; |
| 4116 | ptrdiff_t offset = (char *) p - (char *) &b->floats[0]; | 4253 | ptrdiff_t offset = (char *) p - (char *) &b->floats[0]; |
| 4117 | 4254 | ||
| 4118 | /* P must point to the start of a Lisp_Float and not be | 4255 | /* P must point to the start of a Lisp_Float and not be |
| @@ -4136,7 +4273,7 @@ live_misc_p (struct mem_node *m, void *p) | |||
| 4136 | { | 4273 | { |
| 4137 | if (m->type == MEM_TYPE_MISC) | 4274 | if (m->type == MEM_TYPE_MISC) |
| 4138 | { | 4275 | { |
| 4139 | struct marker_block *b = (struct marker_block *) m->start; | 4276 | struct marker_block *b = m->start; |
| 4140 | ptrdiff_t offset = (char *) p - (char *) &b->markers[0]; | 4277 | ptrdiff_t offset = (char *) p - (char *) &b->markers[0]; |
| 4141 | 4278 | ||
| 4142 | /* P must point to the start of a Lisp_Misc, not be | 4279 | /* P must point to the start of a Lisp_Misc, not be |
| @@ -4163,7 +4300,7 @@ live_vector_p (struct mem_node *m, void *p) | |||
| 4163 | if (m->type == MEM_TYPE_VECTOR_BLOCK) | 4300 | if (m->type == MEM_TYPE_VECTOR_BLOCK) |
| 4164 | { | 4301 | { |
| 4165 | /* This memory node corresponds to a vector block. */ | 4302 | /* This memory node corresponds to a vector block. */ |
| 4166 | struct vector_block *block = (struct vector_block *) m->start; | 4303 | struct vector_block *block = m->start; |
| 4167 | struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data; | 4304 | struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data; |
| 4168 | 4305 | ||
| 4169 | /* P is in the block's allocation range. Scan the block | 4306 | /* P is in the block's allocation range. Scan the block |
| @@ -4180,9 +4317,7 @@ live_vector_p (struct mem_node *m, void *p) | |||
| 4180 | vector = ADVANCE (vector, vector_nbytes (vector)); | 4317 | vector = ADVANCE (vector, vector_nbytes (vector)); |
| 4181 | } | 4318 | } |
| 4182 | } | 4319 | } |
| 4183 | else if (m->type == MEM_TYPE_VECTORLIKE | 4320 | else if (m->type == MEM_TYPE_VECTORLIKE && p == large_vector_vec (m->start)) |
| 4184 | && (char *) p == ((char *) m->start | ||
| 4185 | + offsetof (struct large_vector, v))) | ||
| 4186 | /* This memory node corresponds to a large vector. */ | 4321 | /* This memory node corresponds to a large vector. */ |
| 4187 | return 1; | 4322 | return 1; |
| 4188 | return 0; | 4323 | return 0; |
| @@ -4208,8 +4343,12 @@ live_buffer_p (struct mem_node *m, void *p) | |||
| 4208 | 4343 | ||
| 4209 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 4344 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| 4210 | 4345 | ||
| 4346 | /* Currently not used, but may be called from gdb. */ | ||
| 4347 | |||
| 4348 | void dump_zombies (void) EXTERNALLY_VISIBLE; | ||
| 4349 | |||
| 4211 | /* Array of objects that are kept alive because the C stack contains | 4350 | /* Array of objects that are kept alive because the C stack contains |
| 4212 | a pattern that looks like a reference to them . */ | 4351 | a pattern that looks like a reference to them. */ |
| 4213 | 4352 | ||
| 4214 | #define MAX_ZOMBIES 10 | 4353 | #define MAX_ZOMBIES 10 |
| 4215 | static Lisp_Object zombies[MAX_ZOMBIES]; | 4354 | static Lisp_Object zombies[MAX_ZOMBIES]; |
| @@ -4264,6 +4403,11 @@ mark_maybe_object (Lisp_Object obj) | |||
| 4264 | void *po; | 4403 | void *po; |
| 4265 | struct mem_node *m; | 4404 | struct mem_node *m; |
| 4266 | 4405 | ||
| 4406 | #if USE_VALGRIND | ||
| 4407 | if (valgrind_p) | ||
| 4408 | VALGRIND_MAKE_MEM_DEFINED (&obj, sizeof (obj)); | ||
| 4409 | #endif | ||
| 4410 | |||
| 4267 | if (INTEGERP (obj)) | 4411 | if (INTEGERP (obj)) |
| 4268 | return; | 4412 | return; |
| 4269 | 4413 | ||
| @@ -4332,6 +4476,11 @@ mark_maybe_pointer (void *p) | |||
| 4332 | { | 4476 | { |
| 4333 | struct mem_node *m; | 4477 | struct mem_node *m; |
| 4334 | 4478 | ||
| 4479 | #if USE_VALGRIND | ||
| 4480 | if (valgrind_p) | ||
| 4481 | VALGRIND_MAKE_MEM_DEFINED (&p, sizeof (p)); | ||
| 4482 | #endif | ||
| 4483 | |||
| 4335 | /* Quickly rule out some values which can't point to Lisp data. | 4484 | /* Quickly rule out some values which can't point to Lisp data. |
| 4336 | USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT. | 4485 | USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT. |
| 4337 | Otherwise, assume that Lisp data is aligned on even addresses. */ | 4486 | Otherwise, assume that Lisp data is aligned on even addresses. */ |
| @@ -4431,16 +4580,8 @@ mark_maybe_pointer (void *p) | |||
| 4431 | /* Mark Lisp objects referenced from the address range START+OFFSET..END | 4580 | /* Mark Lisp objects referenced from the address range START+OFFSET..END |
| 4432 | or END+OFFSET..START. */ | 4581 | or END+OFFSET..START. */ |
| 4433 | 4582 | ||
| 4434 | static void | 4583 | static void ATTRIBUTE_NO_SANITIZE_ADDRESS |
| 4435 | mark_memory (void *start, void *end) | 4584 | mark_memory (void *start, void *end) |
| 4436 | #if defined (__clang__) && defined (__has_feature) | ||
| 4437 | #if __has_feature(address_sanitizer) | ||
| 4438 | /* Do not allow -faddress-sanitizer to check this function, since it | ||
| 4439 | crosses the function stack boundary, and thus would yield many | ||
| 4440 | false positives. */ | ||
| 4441 | __attribute__((no_address_safety_analysis)) | ||
| 4442 | #endif | ||
| 4443 | #endif | ||
| 4444 | { | 4585 | { |
| 4445 | void **pp; | 4586 | void **pp; |
| 4446 | int i; | 4587 | int i; |
| @@ -4590,7 +4731,7 @@ check_gcpros (void) | |||
| 4590 | 4731 | ||
| 4591 | #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 4732 | #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| 4592 | 4733 | ||
| 4593 | static void | 4734 | void |
| 4594 | dump_zombies (void) | 4735 | dump_zombies (void) |
| 4595 | { | 4736 | { |
| 4596 | int i; | 4737 | int i; |
| @@ -4727,6 +4868,10 @@ mark_stack (void) | |||
| 4727 | #endif | 4868 | #endif |
| 4728 | } | 4869 | } |
| 4729 | 4870 | ||
| 4871 | #else /* GC_MARK_STACK == 0 */ | ||
| 4872 | |||
| 4873 | #define mark_maybe_object(obj) emacs_abort () | ||
| 4874 | |||
| 4730 | #endif /* GC_MARK_STACK != 0 */ | 4875 | #endif /* GC_MARK_STACK != 0 */ |
| 4731 | 4876 | ||
| 4732 | 4877 | ||
| @@ -4744,9 +4889,9 @@ valid_pointer_p (void *p) | |||
| 4744 | Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may | 4889 | Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may |
| 4745 | not validate p in that case. */ | 4890 | not validate p in that case. */ |
| 4746 | 4891 | ||
| 4747 | if (pipe (fd) == 0) | 4892 | if (emacs_pipe (fd) == 0) |
| 4748 | { | 4893 | { |
| 4749 | bool valid = emacs_write (fd[1], (char *) p, 16) == 16; | 4894 | bool valid = emacs_write (fd[1], p, 16) == 16; |
| 4750 | emacs_close (fd[1]); | 4895 | emacs_close (fd[1]); |
| 4751 | emacs_close (fd[0]); | 4896 | emacs_close (fd[0]); |
| 4752 | return valid; | 4897 | return valid; |
| @@ -5128,9 +5273,9 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 5128 | void | 5273 | void |
| 5129 | staticpro (Lisp_Object *varaddress) | 5274 | staticpro (Lisp_Object *varaddress) |
| 5130 | { | 5275 | { |
| 5131 | staticvec[staticidx++] = varaddress; | ||
| 5132 | if (staticidx >= NSTATICS) | 5276 | if (staticidx >= NSTATICS) |
| 5133 | fatal ("NSTATICS too small; try increasing and recompiling Emacs."); | 5277 | fatal ("NSTATICS too small; try increasing and recompiling Emacs."); |
| 5278 | staticvec[staticidx++] = varaddress; | ||
| 5134 | } | 5279 | } |
| 5135 | 5280 | ||
| 5136 | 5281 | ||
| @@ -5175,6 +5320,102 @@ total_bytes_of_live_objects (void) | |||
| 5175 | return tot; | 5320 | return tot; |
| 5176 | } | 5321 | } |
| 5177 | 5322 | ||
| 5323 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 5324 | |||
| 5325 | /* This code has a few issues on MS-Windows, see Bug#15876 and Bug#16140. */ | ||
| 5326 | |||
| 5327 | #if !defined (HAVE_NTGUI) | ||
| 5328 | |||
| 5329 | /* Remove unmarked font-spec and font-entity objects from ENTRY, which is | ||
| 5330 | (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...), and return changed entry. */ | ||
| 5331 | |||
| 5332 | static Lisp_Object | ||
| 5333 | compact_font_cache_entry (Lisp_Object entry) | ||
| 5334 | { | ||
| 5335 | Lisp_Object tail, *prev = &entry; | ||
| 5336 | |||
| 5337 | for (tail = entry; CONSP (tail); tail = XCDR (tail)) | ||
| 5338 | { | ||
| 5339 | bool drop = 0; | ||
| 5340 | Lisp_Object obj = XCAR (tail); | ||
| 5341 | |||
| 5342 | /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]). */ | ||
| 5343 | if (CONSP (obj) && FONT_SPEC_P (XCAR (obj)) | ||
| 5344 | && !VECTOR_MARKED_P (XFONT_SPEC (XCAR (obj))) | ||
| 5345 | && VECTORP (XCDR (obj))) | ||
| 5346 | { | ||
| 5347 | ptrdiff_t i, size = ASIZE (XCDR (obj)) & ~ARRAY_MARK_FLAG; | ||
| 5348 | |||
| 5349 | /* If font-spec is not marked, most likely all font-entities | ||
| 5350 | are not marked too. But we must be sure that nothing is | ||
| 5351 | marked within OBJ before we really drop it. */ | ||
| 5352 | for (i = 0; i < size; i++) | ||
| 5353 | if (VECTOR_MARKED_P (XFONT_ENTITY (AREF (XCDR (obj), i)))) | ||
| 5354 | break; | ||
| 5355 | |||
| 5356 | if (i == size) | ||
| 5357 | drop = 1; | ||
| 5358 | } | ||
| 5359 | if (drop) | ||
| 5360 | *prev = XCDR (tail); | ||
| 5361 | else | ||
| 5362 | prev = xcdr_addr (tail); | ||
| 5363 | } | ||
| 5364 | return entry; | ||
| 5365 | } | ||
| 5366 | |||
| 5367 | #endif /* not HAVE_NTGUI */ | ||
| 5368 | |||
| 5369 | /* Compact font caches on all terminals and mark | ||
| 5370 | everything which is still here after compaction. */ | ||
| 5371 | |||
| 5372 | static void | ||
| 5373 | compact_font_caches (void) | ||
| 5374 | { | ||
| 5375 | struct terminal *t; | ||
| 5376 | |||
| 5377 | for (t = terminal_list; t; t = t->next_terminal) | ||
| 5378 | { | ||
| 5379 | Lisp_Object cache = TERMINAL_FONT_CACHE (t); | ||
| 5380 | #if !defined (HAVE_NTGUI) | ||
| 5381 | if (CONSP (cache)) | ||
| 5382 | { | ||
| 5383 | Lisp_Object entry; | ||
| 5384 | |||
| 5385 | for (entry = XCDR (cache); CONSP (entry); entry = XCDR (entry)) | ||
| 5386 | XSETCAR (entry, compact_font_cache_entry (XCAR (entry))); | ||
| 5387 | } | ||
| 5388 | #endif /* not HAVE_NTGUI */ | ||
| 5389 | mark_object (cache); | ||
| 5390 | } | ||
| 5391 | } | ||
| 5392 | |||
| 5393 | #else /* not HAVE_WINDOW_SYSTEM */ | ||
| 5394 | |||
| 5395 | #define compact_font_caches() (void)(0) | ||
| 5396 | |||
| 5397 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 5398 | |||
| 5399 | /* Remove (MARKER . DATA) entries with unmarked MARKER | ||
| 5400 | from buffer undo LIST and return changed list. */ | ||
| 5401 | |||
| 5402 | static Lisp_Object | ||
| 5403 | compact_undo_list (Lisp_Object list) | ||
| 5404 | { | ||
| 5405 | Lisp_Object tail, *prev = &list; | ||
| 5406 | |||
| 5407 | for (tail = list; CONSP (tail); tail = XCDR (tail)) | ||
| 5408 | { | ||
| 5409 | if (CONSP (XCAR (tail)) | ||
| 5410 | && MARKERP (XCAR (XCAR (tail))) | ||
| 5411 | && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) | ||
| 5412 | *prev = XCDR (tail); | ||
| 5413 | else | ||
| 5414 | prev = xcdr_addr (tail); | ||
| 5415 | } | ||
| 5416 | return list; | ||
| 5417 | } | ||
| 5418 | |||
| 5178 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 5419 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| 5179 | doc: /* Reclaim storage for Lisp objects no longer needed. | 5420 | doc: /* Reclaim storage for Lisp objects no longer needed. |
| 5180 | Garbage collection happens automatically if you cons more than | 5421 | Garbage collection happens automatically if you cons more than |
| @@ -5192,16 +5433,14 @@ returns nil, because real GC can't be done. | |||
| 5192 | See Info node `(elisp)Garbage Collection'. */) | 5433 | See Info node `(elisp)Garbage Collection'. */) |
| 5193 | (void) | 5434 | (void) |
| 5194 | { | 5435 | { |
| 5195 | struct specbinding *bind; | ||
| 5196 | struct buffer *nextb; | 5436 | struct buffer *nextb; |
| 5197 | char stack_top_variable; | 5437 | char stack_top_variable; |
| 5198 | ptrdiff_t i; | 5438 | ptrdiff_t i; |
| 5199 | bool message_p; | 5439 | bool message_p; |
| 5200 | ptrdiff_t count = SPECPDL_INDEX (); | 5440 | ptrdiff_t count = SPECPDL_INDEX (); |
| 5201 | EMACS_TIME start; | 5441 | struct timespec start; |
| 5202 | Lisp_Object retval = Qnil; | 5442 | Lisp_Object retval = Qnil; |
| 5203 | size_t tot_before = 0; | 5443 | size_t tot_before = 0; |
| 5204 | struct backtrace backtrace; | ||
| 5205 | 5444 | ||
| 5206 | if (abort_on_gc) | 5445 | if (abort_on_gc) |
| 5207 | emacs_abort (); | 5446 | emacs_abort (); |
| @@ -5212,12 +5451,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5212 | return Qnil; | 5451 | return Qnil; |
| 5213 | 5452 | ||
| 5214 | /* Record this function, so it appears on the profiler's backtraces. */ | 5453 | /* Record this function, so it appears on the profiler's backtraces. */ |
| 5215 | backtrace.next = backtrace_list; | 5454 | record_in_backtrace (Qautomatic_gc, &Qnil, 0); |
| 5216 | backtrace.function = Qautomatic_gc; | ||
| 5217 | backtrace.args = &Qnil; | ||
| 5218 | backtrace.nargs = 0; | ||
| 5219 | backtrace.debug_on_exit = 0; | ||
| 5220 | backtrace_list = &backtrace; | ||
| 5221 | 5455 | ||
| 5222 | check_cons_list (); | 5456 | check_cons_list (); |
| 5223 | 5457 | ||
| @@ -5229,7 +5463,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5229 | if (profiler_memory_running) | 5463 | if (profiler_memory_running) |
| 5230 | tot_before = total_bytes_of_live_objects (); | 5464 | tot_before = total_bytes_of_live_objects (); |
| 5231 | 5465 | ||
| 5232 | start = current_emacs_time (); | 5466 | start = current_timespec (); |
| 5233 | 5467 | ||
| 5234 | /* In case user calls debug_print during GC, | 5468 | /* In case user calls debug_print during GC, |
| 5235 | don't let that cause a recursive GC. */ | 5469 | don't let that cause a recursive GC. */ |
| @@ -5237,7 +5471,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5237 | 5471 | ||
| 5238 | /* Save what's currently displayed in the echo area. */ | 5472 | /* Save what's currently displayed in the echo area. */ |
| 5239 | message_p = push_message (); | 5473 | message_p = push_message (); |
| 5240 | record_unwind_protect (pop_message_unwind, Qnil); | 5474 | record_unwind_protect_void (pop_message_unwind); |
| 5241 | 5475 | ||
| 5242 | /* Save a copy of the contents of the stack, for debugging. */ | 5476 | /* Save a copy of the contents of the stack, for debugging. */ |
| 5243 | #if MAX_SAVE_STACK > 0 | 5477 | #if MAX_SAVE_STACK > 0 |
| @@ -5262,7 +5496,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5262 | stack_copy = xrealloc (stack_copy, stack_size); | 5496 | stack_copy = xrealloc (stack_copy, stack_size); |
| 5263 | stack_copy_size = stack_size; | 5497 | stack_copy_size = stack_size; |
| 5264 | } | 5498 | } |
| 5265 | memcpy (stack_copy, stack, stack_size); | 5499 | no_sanitize_memcpy (stack_copy, stack, stack_size); |
| 5266 | } | 5500 | } |
| 5267 | } | 5501 | } |
| 5268 | #endif /* MAX_SAVE_STACK > 0 */ | 5502 | #endif /* MAX_SAVE_STACK > 0 */ |
| @@ -5284,11 +5518,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5284 | for (i = 0; i < staticidx; i++) | 5518 | for (i = 0; i < staticidx; i++) |
| 5285 | mark_object (*staticvec[i]); | 5519 | mark_object (*staticvec[i]); |
| 5286 | 5520 | ||
| 5287 | for (bind = specpdl; bind != specpdl_ptr; bind++) | 5521 | mark_specpdl (); |
| 5288 | { | ||
| 5289 | mark_object (bind->symbol); | ||
| 5290 | mark_object (bind->old_value); | ||
| 5291 | } | ||
| 5292 | mark_terminals (); | 5522 | mark_terminals (); |
| 5293 | mark_kboards (); | 5523 | mark_kboards (); |
| 5294 | 5524 | ||
| @@ -5307,24 +5537,15 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5307 | mark_object (tail->var[i]); | 5537 | mark_object (tail->var[i]); |
| 5308 | } | 5538 | } |
| 5309 | mark_byte_stack (); | 5539 | mark_byte_stack (); |
| 5540 | #endif | ||
| 5310 | { | 5541 | { |
| 5311 | struct catchtag *catch; | ||
| 5312 | struct handler *handler; | 5542 | struct handler *handler; |
| 5313 | 5543 | for (handler = handlerlist; handler; handler = handler->next) | |
| 5314 | for (catch = catchlist; catch; catch = catch->next) | 5544 | { |
| 5315 | { | 5545 | mark_object (handler->tag_or_ch); |
| 5316 | mark_object (catch->tag); | 5546 | mark_object (handler->val); |
| 5317 | mark_object (catch->val); | 5547 | } |
| 5318 | } | ||
| 5319 | for (handler = handlerlist; handler; handler = handler->next) | ||
| 5320 | { | ||
| 5321 | mark_object (handler->handler); | ||
| 5322 | mark_object (handler->var); | ||
| 5323 | } | ||
| 5324 | } | 5548 | } |
| 5325 | mark_backtrace (); | ||
| 5326 | #endif | ||
| 5327 | |||
| 5328 | #ifdef HAVE_WINDOW_SYSTEM | 5549 | #ifdef HAVE_WINDOW_SYSTEM |
| 5329 | mark_fringe_data (); | 5550 | mark_fringe_data (); |
| 5330 | #endif | 5551 | #endif |
| @@ -5333,46 +5554,19 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5333 | mark_stack (); | 5554 | mark_stack (); |
| 5334 | #endif | 5555 | #endif |
| 5335 | 5556 | ||
| 5336 | /* Everything is now marked, except for the things that require special | 5557 | /* Everything is now marked, except for the data in font caches |
| 5337 | finalization, i.e. the undo_list. | 5558 | and undo lists. They're compacted by removing an items which |
| 5338 | Look thru every buffer's undo list | 5559 | aren't reachable otherwise. */ |
| 5339 | for elements that update markers that were not marked, | 5560 | |
| 5340 | and delete them. */ | 5561 | compact_font_caches (); |
| 5562 | |||
| 5341 | FOR_EACH_BUFFER (nextb) | 5563 | FOR_EACH_BUFFER (nextb) |
| 5342 | { | 5564 | { |
| 5343 | /* If a buffer's undo list is Qt, that means that undo is | 5565 | if (!EQ (BVAR (nextb, undo_list), Qt)) |
| 5344 | turned off in that buffer. Calling truncate_undo_list on | 5566 | bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list))); |
| 5345 | Qt tends to return NULL, which effectively turns undo back on. | 5567 | /* Now that we have stripped the elements that need not be |
| 5346 | So don't call truncate_undo_list if undo_list is Qt. */ | 5568 | in the undo_list any more, we can finally mark the list. */ |
| 5347 | if (! EQ (nextb->INTERNAL_FIELD (undo_list), Qt)) | 5569 | mark_object (BVAR (nextb, undo_list)); |
| 5348 | { | ||
| 5349 | Lisp_Object tail, prev; | ||
| 5350 | tail = nextb->INTERNAL_FIELD (undo_list); | ||
| 5351 | prev = Qnil; | ||
| 5352 | while (CONSP (tail)) | ||
| 5353 | { | ||
| 5354 | if (CONSP (XCAR (tail)) | ||
| 5355 | && MARKERP (XCAR (XCAR (tail))) | ||
| 5356 | && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) | ||
| 5357 | { | ||
| 5358 | if (NILP (prev)) | ||
| 5359 | nextb->INTERNAL_FIELD (undo_list) = tail = XCDR (tail); | ||
| 5360 | else | ||
| 5361 | { | ||
| 5362 | tail = XCDR (tail); | ||
| 5363 | XSETCDR (prev, tail); | ||
| 5364 | } | ||
| 5365 | } | ||
| 5366 | else | ||
| 5367 | { | ||
| 5368 | prev = tail; | ||
| 5369 | tail = XCDR (tail); | ||
| 5370 | } | ||
| 5371 | } | ||
| 5372 | } | ||
| 5373 | /* Now that we have stripped the elements that need not be in the | ||
| 5374 | undo_list any more, we can finally mark the list. */ | ||
| 5375 | mark_object (nextb->INTERNAL_FIELD (undo_list)); | ||
| 5376 | } | 5570 | } |
| 5377 | 5571 | ||
| 5378 | gc_sweep (); | 5572 | gc_sweep (); |
| @@ -5444,7 +5638,8 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5444 | total[4] = list3 (Qstring_bytes, make_number (1), | 5638 | total[4] = list3 (Qstring_bytes, make_number (1), |
| 5445 | bounded_number (total_string_bytes)); | 5639 | bounded_number (total_string_bytes)); |
| 5446 | 5640 | ||
| 5447 | total[5] = list3 (Qvectors, make_number (sizeof (struct Lisp_Vector)), | 5641 | total[5] = list3 (Qvectors, |
| 5642 | make_number (header_size + sizeof (Lisp_Object)), | ||
| 5448 | bounded_number (total_vectors)); | 5643 | bounded_number (total_vectors)); |
| 5449 | 5644 | ||
| 5450 | total[6] = list4 (Qvector_slots, make_number (word_size), | 5645 | total[6] = list4 (Qvector_slots, make_number (word_size), |
| @@ -5496,9 +5691,9 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5496 | /* Accumulate statistics. */ | 5691 | /* Accumulate statistics. */ |
| 5497 | if (FLOATP (Vgc_elapsed)) | 5692 | if (FLOATP (Vgc_elapsed)) |
| 5498 | { | 5693 | { |
| 5499 | EMACS_TIME since_start = sub_emacs_time (current_emacs_time (), start); | 5694 | struct timespec since_start = timespec_sub (current_timespec (), start); |
| 5500 | Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) | 5695 | Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) |
| 5501 | + EMACS_TIME_TO_DOUBLE (since_start)); | 5696 | + timespectod (since_start)); |
| 5502 | } | 5697 | } |
| 5503 | 5698 | ||
| 5504 | gcs_done++; | 5699 | gcs_done++; |
| @@ -5513,7 +5708,6 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5513 | malloc_probe (swept); | 5708 | malloc_probe (swept); |
| 5514 | } | 5709 | } |
| 5515 | 5710 | ||
| 5516 | backtrace_list = backtrace.next; | ||
| 5517 | return retval; | 5711 | return retval; |
| 5518 | } | 5712 | } |
| 5519 | 5713 | ||
| @@ -5544,30 +5738,6 @@ mark_glyph_matrix (struct glyph_matrix *matrix) | |||
| 5544 | } | 5738 | } |
| 5545 | } | 5739 | } |
| 5546 | 5740 | ||
| 5547 | |||
| 5548 | /* Mark Lisp faces in the face cache C. */ | ||
| 5549 | |||
| 5550 | static void | ||
| 5551 | mark_face_cache (struct face_cache *c) | ||
| 5552 | { | ||
| 5553 | if (c) | ||
| 5554 | { | ||
| 5555 | int i, j; | ||
| 5556 | for (i = 0; i < c->used; ++i) | ||
| 5557 | { | ||
| 5558 | struct face *face = FACE_FROM_ID (c->f, i); | ||
| 5559 | |||
| 5560 | if (face) | ||
| 5561 | { | ||
| 5562 | for (j = 0; j < LFACE_VECTOR_SIZE; ++j) | ||
| 5563 | mark_object (face->lface[j]); | ||
| 5564 | } | ||
| 5565 | } | ||
| 5566 | } | ||
| 5567 | } | ||
| 5568 | |||
| 5569 | |||
| 5570 | |||
| 5571 | /* Mark reference to a Lisp_Object. | 5741 | /* Mark reference to a Lisp_Object. |
| 5572 | If the object referred to has not been seen yet, recursively mark | 5742 | If the object referred to has not been seen yet, recursively mark |
| 5573 | all the references contained in it. */ | 5743 | all the references contained in it. */ |
| @@ -5667,6 +5837,30 @@ mark_buffer (struct buffer *buffer) | |||
| 5667 | mark_buffer (buffer->base_buffer); | 5837 | mark_buffer (buffer->base_buffer); |
| 5668 | } | 5838 | } |
| 5669 | 5839 | ||
| 5840 | /* Mark Lisp faces in the face cache C. */ | ||
| 5841 | |||
| 5842 | static void | ||
| 5843 | mark_face_cache (struct face_cache *c) | ||
| 5844 | { | ||
| 5845 | if (c) | ||
| 5846 | { | ||
| 5847 | int i, j; | ||
| 5848 | for (i = 0; i < c->used; ++i) | ||
| 5849 | { | ||
| 5850 | struct face *face = FACE_FROM_ID (c->f, i); | ||
| 5851 | |||
| 5852 | if (face) | ||
| 5853 | { | ||
| 5854 | if (face->font && !VECTOR_MARKED_P (face->font)) | ||
| 5855 | mark_vectorlike ((struct Lisp_Vector *) face->font); | ||
| 5856 | |||
| 5857 | for (j = 0; j < LFACE_VECTOR_SIZE; ++j) | ||
| 5858 | mark_object (face->lface[j]); | ||
| 5859 | } | ||
| 5860 | } | ||
| 5861 | } | ||
| 5862 | } | ||
| 5863 | |||
| 5670 | /* Remove killed buffers or items whose car is a killed buffer from | 5864 | /* Remove killed buffers or items whose car is a killed buffer from |
| 5671 | LIST, and mark other items. Return changed LIST, which is marked. */ | 5865 | LIST, and mark other items. Return changed LIST, which is marked. */ |
| 5672 | 5866 | ||
| @@ -5687,7 +5881,7 @@ mark_discard_killed_buffers (Lisp_Object list) | |||
| 5687 | { | 5881 | { |
| 5688 | CONS_MARK (XCONS (tail)); | 5882 | CONS_MARK (XCONS (tail)); |
| 5689 | mark_object (XCAR (tail)); | 5883 | mark_object (XCAR (tail)); |
| 5690 | prev = &XCDR_AS_LVALUE (tail); | 5884 | prev = xcdr_addr (tail); |
| 5691 | } | 5885 | } |
| 5692 | } | 5886 | } |
| 5693 | mark_object (tail); | 5887 | mark_object (tail); |
| @@ -5830,21 +6024,33 @@ mark_object (Lisp_Object arg) | |||
| 5830 | break; | 6024 | break; |
| 5831 | 6025 | ||
| 5832 | case PVEC_FRAME: | 6026 | case PVEC_FRAME: |
| 5833 | mark_vectorlike (ptr); | 6027 | { |
| 5834 | mark_face_cache (((struct frame *) ptr)->face_cache); | 6028 | struct frame *f = (struct frame *) ptr; |
| 6029 | |||
| 6030 | mark_vectorlike (ptr); | ||
| 6031 | mark_face_cache (f->face_cache); | ||
| 6032 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 6033 | if (FRAME_WINDOW_P (f) && FRAME_X_OUTPUT (f)) | ||
| 6034 | { | ||
| 6035 | struct font *font = FRAME_FONT (f); | ||
| 6036 | |||
| 6037 | if (font && !VECTOR_MARKED_P (font)) | ||
| 6038 | mark_vectorlike ((struct Lisp_Vector *) font); | ||
| 6039 | } | ||
| 6040 | #endif | ||
| 6041 | } | ||
| 5835 | break; | 6042 | break; |
| 5836 | 6043 | ||
| 5837 | case PVEC_WINDOW: | 6044 | case PVEC_WINDOW: |
| 5838 | { | 6045 | { |
| 5839 | struct window *w = (struct window *) ptr; | 6046 | struct window *w = (struct window *) ptr; |
| 5840 | bool leaf = NILP (w->hchild) && NILP (w->vchild); | ||
| 5841 | 6047 | ||
| 5842 | mark_vectorlike (ptr); | 6048 | mark_vectorlike (ptr); |
| 5843 | 6049 | ||
| 5844 | /* Mark glyphs for leaf windows. Marking window | 6050 | /* Mark glyph matrices, if any. Marking window |
| 5845 | matrices is sufficient because frame matrices | 6051 | matrices is sufficient because frame matrices |
| 5846 | use the same glyph memory. */ | 6052 | use the same glyph memory. */ |
| 5847 | if (leaf && w->current_matrix) | 6053 | if (w->current_matrix) |
| 5848 | { | 6054 | { |
| 5849 | mark_glyph_matrix (w->current_matrix); | 6055 | mark_glyph_matrix (w->current_matrix); |
| 5850 | mark_glyph_matrix (w->desired_matrix); | 6056 | mark_glyph_matrix (w->desired_matrix); |
| @@ -5976,12 +6182,11 @@ mark_object (Lisp_Object arg) | |||
| 5976 | case Lisp_Misc_Save_Value: | 6182 | case Lisp_Misc_Save_Value: |
| 5977 | XMISCANY (obj)->gcmarkbit = 1; | 6183 | XMISCANY (obj)->gcmarkbit = 1; |
| 5978 | { | 6184 | { |
| 5979 | register struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); | 6185 | struct Lisp_Save_Value *ptr = XSAVE_VALUE (obj); |
| 5980 | /* If `area' is nonzero, `data[0].pointer' is the address | 6186 | /* If `save_type' is zero, `data[0].pointer' is the address |
| 5981 | of a memory area containing `data[1].integer' potential | 6187 | of a memory area containing `data[1].integer' potential |
| 5982 | Lisp_Objects. */ | 6188 | Lisp_Objects. */ |
| 5983 | #if GC_MARK_STACK | 6189 | if (GC_MARK_STACK && ptr->save_type == SAVE_TYPE_MEMORY) |
| 5984 | if (ptr->area) | ||
| 5985 | { | 6190 | { |
| 5986 | Lisp_Object *p = ptr->data[0].pointer; | 6191 | Lisp_Object *p = ptr->data[0].pointer; |
| 5987 | ptrdiff_t nelt; | 6192 | ptrdiff_t nelt; |
| @@ -5989,17 +6194,12 @@ mark_object (Lisp_Object arg) | |||
| 5989 | mark_maybe_object (*p); | 6194 | mark_maybe_object (*p); |
| 5990 | } | 6195 | } |
| 5991 | else | 6196 | else |
| 5992 | #endif /* GC_MARK_STACK */ | ||
| 5993 | { | 6197 | { |
| 5994 | /* Find Lisp_Objects in `data[N]' slots and mark them. */ | 6198 | /* Find Lisp_Objects in `data[N]' slots and mark them. */ |
| 5995 | if (ptr->type0 == SAVE_OBJECT) | 6199 | int i; |
| 5996 | mark_object (ptr->data[0].object); | 6200 | for (i = 0; i < SAVE_VALUE_SLOTS; i++) |
| 5997 | if (ptr->type1 == SAVE_OBJECT) | 6201 | if (save_type (ptr, i) == SAVE_OBJECT) |
| 5998 | mark_object (ptr->data[1].object); | 6202 | mark_object (ptr->data[i].object); |
| 5999 | if (ptr->type2 == SAVE_OBJECT) | ||
| 6000 | mark_object (ptr->data[2].object); | ||
| 6001 | if (ptr->type3 == SAVE_OBJECT) | ||
| 6002 | mark_object (ptr->data[3].object); | ||
| 6003 | } | 6203 | } |
| 6004 | } | 6204 | } |
| 6005 | break; | 6205 | break; |
| @@ -6121,7 +6321,7 @@ survives_gc_p (Lisp_Object obj) | |||
| 6121 | 6321 | ||
| 6122 | 6322 | ||
| 6123 | 6323 | ||
| 6124 | /* Sweep: find all structures not marked, and free them. */ | 6324 | /* Sweep: find all structures not marked, and free them. */ |
| 6125 | 6325 | ||
| 6126 | static void | 6326 | static void |
| 6127 | gc_sweep (void) | 6327 | gc_sweep (void) |
| @@ -6133,7 +6333,7 @@ gc_sweep (void) | |||
| 6133 | sweep_strings (); | 6333 | sweep_strings (); |
| 6134 | check_string_bytes (!noninteractive); | 6334 | check_string_bytes (!noninteractive); |
| 6135 | 6335 | ||
| 6136 | /* Put all unmarked conses on free list */ | 6336 | /* Put all unmarked conses on free list. */ |
| 6137 | { | 6337 | { |
| 6138 | register struct cons_block *cblk; | 6338 | register struct cons_block *cblk; |
| 6139 | struct cons_block **cprev = &cons_block; | 6339 | struct cons_block **cprev = &cons_block; |
| @@ -6210,7 +6410,7 @@ gc_sweep (void) | |||
| 6210 | total_free_conses = num_free; | 6410 | total_free_conses = num_free; |
| 6211 | } | 6411 | } |
| 6212 | 6412 | ||
| 6213 | /* Put all unmarked floats on free list */ | 6413 | /* Put all unmarked floats on free list. */ |
| 6214 | { | 6414 | { |
| 6215 | register struct float_block *fblk; | 6415 | register struct float_block *fblk; |
| 6216 | struct float_block **fprev = &float_block; | 6416 | struct float_block **fprev = &float_block; |
| @@ -6256,7 +6456,7 @@ gc_sweep (void) | |||
| 6256 | total_free_floats = num_free; | 6456 | total_free_floats = num_free; |
| 6257 | } | 6457 | } |
| 6258 | 6458 | ||
| 6259 | /* Put all unmarked intervals on free list */ | 6459 | /* Put all unmarked intervals on free list. */ |
| 6260 | { | 6460 | { |
| 6261 | register struct interval_block *iblk; | 6461 | register struct interval_block *iblk; |
| 6262 | struct interval_block **iprev = &interval_block; | 6462 | struct interval_block **iprev = &interval_block; |
| @@ -6305,7 +6505,7 @@ gc_sweep (void) | |||
| 6305 | total_free_intervals = num_free; | 6505 | total_free_intervals = num_free; |
| 6306 | } | 6506 | } |
| 6307 | 6507 | ||
| 6308 | /* Put all unmarked symbols on free list */ | 6508 | /* Put all unmarked symbols on free list. */ |
| 6309 | { | 6509 | { |
| 6310 | register struct symbol_block *sblk; | 6510 | register struct symbol_block *sblk; |
| 6311 | struct symbol_block **sprev = &symbol_block; | 6511 | struct symbol_block **sprev = &symbol_block; |
| @@ -6342,7 +6542,7 @@ gc_sweep (void) | |||
| 6342 | { | 6542 | { |
| 6343 | ++num_used; | 6543 | ++num_used; |
| 6344 | if (!pure_p) | 6544 | if (!pure_p) |
| 6345 | UNMARK_STRING (XSTRING (sym->s.name)); | 6545 | eassert (!STRING_MARKED_P (XSTRING (sym->s.name))); |
| 6346 | sym->s.gcmarkbit = 0; | 6546 | sym->s.gcmarkbit = 0; |
| 6347 | } | 6547 | } |
| 6348 | } | 6548 | } |
| @@ -6463,7 +6663,12 @@ We divide the value by 1024 to make sure it fits in a Lisp integer. */) | |||
| 6463 | { | 6663 | { |
| 6464 | Lisp_Object end; | 6664 | Lisp_Object end; |
| 6465 | 6665 | ||
| 6666 | #ifdef HAVE_NS | ||
| 6667 | /* Avoid warning. sbrk has no relation to memory allocated anyway. */ | ||
| 6668 | XSETINT (end, 0); | ||
| 6669 | #else | ||
| 6466 | XSETINT (end, (intptr_t) (char *) sbrk (0) / 1024); | 6670 | XSETINT (end, (intptr_t) (char *) sbrk (0) / 1024); |
| 6671 | #endif | ||
| 6467 | 6672 | ||
| 6468 | return end; | 6673 | return end; |
| 6469 | } | 6674 | } |
| @@ -6551,7 +6756,7 @@ bool suppress_checking; | |||
| 6551 | void | 6756 | void |
| 6552 | die (const char *msg, const char *file, int line) | 6757 | die (const char *msg, const char *file, int line) |
| 6553 | { | 6758 | { |
| 6554 | fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n", | 6759 | fprintf (stderr, "\r\n%s:%d: Emacs fatal error: assertion failed: %s\r\n", |
| 6555 | file, line, msg); | 6760 | file, line, msg); |
| 6556 | terminate_due_to_signal (SIGABRT, INT_MAX); | 6761 | terminate_due_to_signal (SIGABRT, INT_MAX); |
| 6557 | } | 6762 | } |
| @@ -6595,6 +6800,10 @@ init_alloc (void) | |||
| 6595 | #endif | 6800 | #endif |
| 6596 | Vgc_elapsed = make_float (0.0); | 6801 | Vgc_elapsed = make_float (0.0); |
| 6597 | gcs_done = 0; | 6802 | gcs_done = 0; |
| 6803 | |||
| 6804 | #if USE_VALGRIND | ||
| 6805 | valgrind_p = RUNNING_ON_VALGRIND != 0; | ||
| 6806 | #endif | ||
| 6598 | } | 6807 | } |
| 6599 | 6808 | ||
| 6600 | void | 6809 | void |
| @@ -6736,8 +6945,5 @@ union | |||
| 6736 | enum MAX_ALLOCA MAX_ALLOCA; | 6945 | enum MAX_ALLOCA MAX_ALLOCA; |
| 6737 | enum More_Lisp_Bits More_Lisp_Bits; | 6946 | enum More_Lisp_Bits More_Lisp_Bits; |
| 6738 | enum pvec_type pvec_type; | 6947 | enum pvec_type pvec_type; |
| 6739 | #if USE_LSB_TAG | ||
| 6740 | enum lsb_bits lsb_bits; | ||
| 6741 | #endif | ||
| 6742 | } const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0}; | 6948 | } const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0}; |
| 6743 | #endif /* __GNUC__ */ | 6949 | #endif /* __GNUC__ */ |