diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 147 |
1 files changed, 90 insertions, 57 deletions
diff --git a/src/alloc.c b/src/alloc.c index ecea3e8ac7d..712c8f771f7 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -263,23 +263,6 @@ no_sanitize_memcpy (void *dest, void const *src, size_t size) | |||
| 263 | 263 | ||
| 264 | #endif /* MAX_SAVE_STACK > 0 */ | 264 | #endif /* MAX_SAVE_STACK > 0 */ |
| 265 | 265 | ||
| 266 | static Lisp_Object Qconses; | ||
| 267 | static Lisp_Object Qsymbols; | ||
| 268 | static Lisp_Object Qmiscs; | ||
| 269 | static Lisp_Object Qstrings; | ||
| 270 | static Lisp_Object Qvectors; | ||
| 271 | static Lisp_Object Qfloats; | ||
| 272 | static Lisp_Object Qintervals; | ||
| 273 | static Lisp_Object Qbuffers; | ||
| 274 | static Lisp_Object Qstring_bytes, Qvector_slots, Qheap; | ||
| 275 | static Lisp_Object Qgc_cons_threshold; | ||
| 276 | Lisp_Object Qautomatic_gc; | ||
| 277 | Lisp_Object Qchar_table_extra_slots; | ||
| 278 | |||
| 279 | /* Hook run after GC has finished. */ | ||
| 280 | |||
| 281 | static Lisp_Object Qpost_gc_hook; | ||
| 282 | |||
| 283 | static void mark_terminals (void); | 266 | static void mark_terminals (void); |
| 284 | static void gc_sweep (void); | 267 | static void gc_sweep (void); |
| 285 | static Lisp_Object make_pure_vector (ptrdiff_t); | 268 | static Lisp_Object make_pure_vector (ptrdiff_t); |
| @@ -3410,13 +3393,29 @@ set_symbol_name (Lisp_Object sym, Lisp_Object name) | |||
| 3410 | XSYMBOL (sym)->name = name; | 3393 | XSYMBOL (sym)->name = name; |
| 3411 | } | 3394 | } |
| 3412 | 3395 | ||
| 3396 | void | ||
| 3397 | init_symbol (Lisp_Object val, Lisp_Object name) | ||
| 3398 | { | ||
| 3399 | struct Lisp_Symbol *p = XSYMBOL (val); | ||
| 3400 | set_symbol_name (val, name); | ||
| 3401 | set_symbol_plist (val, Qnil); | ||
| 3402 | p->redirect = SYMBOL_PLAINVAL; | ||
| 3403 | SET_SYMBOL_VAL (p, Qunbound); | ||
| 3404 | set_symbol_function (val, Qnil); | ||
| 3405 | set_symbol_next (val, NULL); | ||
| 3406 | p->gcmarkbit = false; | ||
| 3407 | p->interned = SYMBOL_UNINTERNED; | ||
| 3408 | p->constant = 0; | ||
| 3409 | p->declared_special = false; | ||
| 3410 | p->pinned = false; | ||
| 3411 | } | ||
| 3412 | |||
| 3413 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, | 3413 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, |
| 3414 | doc: /* Return a newly allocated uninterned symbol whose name is NAME. | 3414 | doc: /* Return a newly allocated uninterned symbol whose name is NAME. |
| 3415 | Its value is void, and its function definition and property list are nil. */) | 3415 | Its value is void, and its function definition and property list are nil. */) |
| 3416 | (Lisp_Object name) | 3416 | (Lisp_Object name) |
| 3417 | { | 3417 | { |
| 3418 | register Lisp_Object val; | 3418 | Lisp_Object val; |
| 3419 | register struct Lisp_Symbol *p; | ||
| 3420 | 3419 | ||
| 3421 | CHECK_STRING (name); | 3420 | CHECK_STRING (name); |
| 3422 | 3421 | ||
| @@ -3444,18 +3443,7 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3444 | 3443 | ||
| 3445 | MALLOC_UNBLOCK_INPUT; | 3444 | MALLOC_UNBLOCK_INPUT; |
| 3446 | 3445 | ||
| 3447 | p = XSYMBOL (val); | 3446 | init_symbol (val, name); |
| 3448 | set_symbol_name (val, name); | ||
| 3449 | set_symbol_plist (val, Qnil); | ||
| 3450 | p->redirect = SYMBOL_PLAINVAL; | ||
| 3451 | SET_SYMBOL_VAL (p, Qunbound); | ||
| 3452 | set_symbol_function (val, Qnil); | ||
| 3453 | set_symbol_next (val, NULL); | ||
| 3454 | p->gcmarkbit = false; | ||
| 3455 | p->interned = SYMBOL_UNINTERNED; | ||
| 3456 | p->constant = 0; | ||
| 3457 | p->declared_special = false; | ||
| 3458 | p->pinned = false; | ||
| 3459 | consing_since_gc += sizeof (struct Lisp_Symbol); | 3447 | consing_since_gc += sizeof (struct Lisp_Symbol); |
| 3460 | symbols_consed++; | 3448 | symbols_consed++; |
| 3461 | total_free_symbols--; | 3449 | total_free_symbols--; |
| @@ -4925,6 +4913,14 @@ mark_stack (void *end) | |||
| 4925 | 4913 | ||
| 4926 | #endif /* GC_MARK_STACK != 0 */ | 4914 | #endif /* GC_MARK_STACK != 0 */ |
| 4927 | 4915 | ||
| 4916 | static bool | ||
| 4917 | c_symbol_p (struct Lisp_Symbol *sym) | ||
| 4918 | { | ||
| 4919 | char *lispsym_ptr = (char *) lispsym; | ||
| 4920 | char *sym_ptr = (char *) sym; | ||
| 4921 | ptrdiff_t lispsym_offset = sym_ptr - lispsym_ptr; | ||
| 4922 | return 0 <= lispsym_offset && lispsym_offset < sizeof lispsym; | ||
| 4923 | } | ||
| 4928 | 4924 | ||
| 4929 | /* Determine whether it is safe to access memory at address P. */ | 4925 | /* Determine whether it is safe to access memory at address P. */ |
| 4930 | static int | 4926 | static int |
| @@ -4978,6 +4974,9 @@ valid_lisp_object_p (Lisp_Object obj) | |||
| 4978 | if (PURE_POINTER_P (p)) | 4974 | if (PURE_POINTER_P (p)) |
| 4979 | return 1; | 4975 | return 1; |
| 4980 | 4976 | ||
| 4977 | if (SYMBOLP (obj) && c_symbol_p (p)) | ||
| 4978 | return ((char *) p - (char *) lispsym) % sizeof lispsym[0] == 0; | ||
| 4979 | |||
| 4981 | if (p == &buffer_defaults || p == &buffer_local_symbols) | 4980 | if (p == &buffer_defaults || p == &buffer_local_symbols) |
| 4982 | return 2; | 4981 | return 2; |
| 4983 | 4982 | ||
| @@ -5343,7 +5342,7 @@ purecopy (Lisp_Object obj) | |||
| 5343 | } | 5342 | } |
| 5344 | else if (SYMBOLP (obj)) | 5343 | else if (SYMBOLP (obj)) |
| 5345 | { | 5344 | { |
| 5346 | if (!XSYMBOL (obj)->pinned) | 5345 | if (!XSYMBOL (obj)->pinned && !c_symbol_p (XSYMBOL (obj))) |
| 5347 | { /* We can't purify them, but they appear in many pure objects. | 5346 | { /* We can't purify them, but they appear in many pure objects. |
| 5348 | Mark them as `pinned' so we know to mark them at every GC cycle. */ | 5347 | Mark them as `pinned' so we know to mark them at every GC cycle. */ |
| 5349 | XSYMBOL (obj)->pinned = true; | 5348 | XSYMBOL (obj)->pinned = true; |
| @@ -5532,7 +5531,7 @@ mark_pinned_symbols (void) | |||
| 5532 | union aligned_Lisp_Symbol *sym = sblk->symbols, *end = sym + lim; | 5531 | union aligned_Lisp_Symbol *sym = sblk->symbols, *end = sym + lim; |
| 5533 | for (; sym < end; ++sym) | 5532 | for (; sym < end; ++sym) |
| 5534 | if (sym->s.pinned) | 5533 | if (sym->s.pinned) |
| 5535 | mark_object (make_lisp_ptr (&sym->s, Lisp_Symbol)); | 5534 | mark_object (make_lisp_symbol (&sym->s)); |
| 5536 | 5535 | ||
| 5537 | lim = SYMBOL_BLOCK_SIZE; | 5536 | lim = SYMBOL_BLOCK_SIZE; |
| 5538 | } | 5537 | } |
| @@ -5566,7 +5565,7 @@ garbage_collect_1 (void *end) | |||
| 5566 | return Qnil; | 5565 | return Qnil; |
| 5567 | 5566 | ||
| 5568 | /* Record this function, so it appears on the profiler's backtraces. */ | 5567 | /* Record this function, so it appears on the profiler's backtraces. */ |
| 5569 | record_in_backtrace (Qautomatic_gc, &Qnil, 0); | 5568 | record_in_backtrace (Qautomatic_gc, 0, 0); |
| 5570 | 5569 | ||
| 5571 | check_cons_list (); | 5570 | check_cons_list (); |
| 5572 | 5571 | ||
| @@ -5630,6 +5629,9 @@ garbage_collect_1 (void *end) | |||
| 5630 | mark_buffer (&buffer_defaults); | 5629 | mark_buffer (&buffer_defaults); |
| 5631 | mark_buffer (&buffer_local_symbols); | 5630 | mark_buffer (&buffer_local_symbols); |
| 5632 | 5631 | ||
| 5632 | for (i = 0; i < ARRAYELTS (lispsym); i++) | ||
| 5633 | mark_object (make_lisp_symbol (&lispsym[i])); | ||
| 5634 | |||
| 5633 | for (i = 0; i < staticidx; i++) | 5635 | for (i = 0; i < staticidx; i++) |
| 5634 | mark_object (*staticvec[i]); | 5636 | mark_object (*staticvec[i]); |
| 5635 | 5637 | ||
| @@ -6193,17 +6195,28 @@ mark_object (Lisp_Object arg) | |||
| 6193 | emacs_abort (); \ | 6195 | emacs_abort (); \ |
| 6194 | } while (0) | 6196 | } while (0) |
| 6195 | 6197 | ||
| 6196 | /* Check both of the above conditions. */ | 6198 | /* Check both of the above conditions, for non-symbols. */ |
| 6197 | #define CHECK_ALLOCATED_AND_LIVE(LIVEP) \ | 6199 | #define CHECK_ALLOCATED_AND_LIVE(LIVEP) \ |
| 6198 | do { \ | 6200 | do { \ |
| 6199 | CHECK_ALLOCATED (); \ | 6201 | CHECK_ALLOCATED (); \ |
| 6200 | CHECK_LIVE (LIVEP); \ | 6202 | CHECK_LIVE (LIVEP); \ |
| 6201 | } while (0) \ | 6203 | } while (0) \ |
| 6202 | 6204 | ||
| 6205 | /* Check both of the above conditions, for symbols. */ | ||
| 6206 | #define CHECK_ALLOCATED_AND_LIVE_SYMBOL() \ | ||
| 6207 | do { \ | ||
| 6208 | if (!c_symbol_p (ptr)) \ | ||
| 6209 | { \ | ||
| 6210 | CHECK_ALLOCATED (); \ | ||
| 6211 | CHECK_LIVE (live_symbol_p); \ | ||
| 6212 | } \ | ||
| 6213 | } while (0) \ | ||
| 6214 | |||
| 6203 | #else /* not GC_CHECK_MARKED_OBJECTS */ | 6215 | #else /* not GC_CHECK_MARKED_OBJECTS */ |
| 6204 | 6216 | ||
| 6205 | #define CHECK_LIVE(LIVEP) ((void) 0) | 6217 | #define CHECK_LIVE(LIVEP) ((void) 0) |
| 6206 | #define CHECK_ALLOCATED_AND_LIVE(LIVEP) ((void) 0) | 6218 | #define CHECK_ALLOCATED_AND_LIVE(LIVEP) ((void) 0) |
| 6219 | #define CHECK_ALLOCATED_AND_LIVE_SYMBOL() ((void) 0) | ||
| 6207 | 6220 | ||
| 6208 | #endif /* not GC_CHECK_MARKED_OBJECTS */ | 6221 | #endif /* not GC_CHECK_MARKED_OBJECTS */ |
| 6209 | 6222 | ||
| @@ -6363,7 +6376,7 @@ mark_object (Lisp_Object arg) | |||
| 6363 | nextsym: | 6376 | nextsym: |
| 6364 | if (ptr->gcmarkbit) | 6377 | if (ptr->gcmarkbit) |
| 6365 | break; | 6378 | break; |
| 6366 | CHECK_ALLOCATED_AND_LIVE (live_symbol_p); | 6379 | CHECK_ALLOCATED_AND_LIVE_SYMBOL (); |
| 6367 | ptr->gcmarkbit = 1; | 6380 | ptr->gcmarkbit = 1; |
| 6368 | /* Attempt to catch bogus objects. */ | 6381 | /* Attempt to catch bogus objects. */ |
| 6369 | eassert (valid_lisp_object_p (ptr->function)); | 6382 | eassert (valid_lisp_object_p (ptr->function)); |
| @@ -6720,13 +6733,16 @@ NO_INLINE /* For better stack traces */ | |||
| 6720 | static void | 6733 | static void |
| 6721 | sweep_symbols (void) | 6734 | sweep_symbols (void) |
| 6722 | { | 6735 | { |
| 6723 | register struct symbol_block *sblk; | 6736 | struct symbol_block *sblk; |
| 6724 | struct symbol_block **sprev = &symbol_block; | 6737 | struct symbol_block **sprev = &symbol_block; |
| 6725 | register int lim = symbol_block_index; | 6738 | int lim = symbol_block_index; |
| 6726 | EMACS_INT num_free = 0, num_used = 0; | 6739 | EMACS_INT num_free = 0, num_used = ARRAYELTS (lispsym); |
| 6727 | 6740 | ||
| 6728 | symbol_free_list = NULL; | 6741 | symbol_free_list = NULL; |
| 6729 | 6742 | ||
| 6743 | for (int i = 0; i < ARRAYELTS (lispsym); i++) | ||
| 6744 | lispsym[i].gcmarkbit = 0; | ||
| 6745 | |||
| 6730 | for (sblk = symbol_block; sblk; sblk = *sprev) | 6746 | for (sblk = symbol_block; sblk; sblk = *sprev) |
| 6731 | { | 6747 | { |
| 6732 | int this_free = 0; | 6748 | int this_free = 0; |
| @@ -6974,6 +6990,21 @@ Frames, windows, buffers, and subprocesses count as vectors | |||
| 6974 | bounded_number (strings_consed)); | 6990 | bounded_number (strings_consed)); |
| 6975 | } | 6991 | } |
| 6976 | 6992 | ||
| 6993 | static bool | ||
| 6994 | symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj) | ||
| 6995 | { | ||
| 6996 | struct Lisp_Symbol *sym = XSYMBOL (symbol); | ||
| 6997 | Lisp_Object val = find_symbol_value (symbol); | ||
| 6998 | return (EQ (val, obj) | ||
| 6999 | || EQ (sym->function, obj) | ||
| 7000 | || (!NILP (sym->function) | ||
| 7001 | && COMPILEDP (sym->function) | ||
| 7002 | && EQ (AREF (sym->function, COMPILED_BYTECODE), obj)) | ||
| 7003 | || (!NILP (val) | ||
| 7004 | && COMPILEDP (val) | ||
| 7005 | && EQ (AREF (val, COMPILED_BYTECODE), obj))); | ||
| 7006 | } | ||
| 7007 | |||
| 6977 | /* Find at most FIND_MAX symbols which have OBJ as their value or | 7008 | /* Find at most FIND_MAX symbols which have OBJ as their value or |
| 6978 | function. This is used in gdbinit's `xwhichsymbols' command. */ | 7009 | function. This is used in gdbinit's `xwhichsymbols' command. */ |
| 6979 | 7010 | ||
| @@ -6986,6 +7017,17 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) | |||
| 6986 | 7017 | ||
| 6987 | if (! DEADP (obj)) | 7018 | if (! DEADP (obj)) |
| 6988 | { | 7019 | { |
| 7020 | for (int i = 0; i < ARRAYELTS (lispsym); i++) | ||
| 7021 | { | ||
| 7022 | Lisp_Object sym = make_lisp_symbol (&lispsym[i]); | ||
| 7023 | if (symbol_uses_obj (sym, obj)) | ||
| 7024 | { | ||
| 7025 | found = Fcons (sym, found); | ||
| 7026 | if (--find_max == 0) | ||
| 7027 | goto out; | ||
| 7028 | } | ||
| 7029 | } | ||
| 7030 | |||
| 6989 | for (sblk = symbol_block; sblk; sblk = sblk->next) | 7031 | for (sblk = symbol_block; sblk; sblk = sblk->next) |
| 6990 | { | 7032 | { |
| 6991 | union aligned_Lisp_Symbol *aligned_sym = sblk->symbols; | 7033 | union aligned_Lisp_Symbol *aligned_sym = sblk->symbols; |
| @@ -6993,25 +7035,13 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) | |||
| 6993 | 7035 | ||
| 6994 | for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, aligned_sym++) | 7036 | for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, aligned_sym++) |
| 6995 | { | 7037 | { |
| 6996 | struct Lisp_Symbol *sym = &aligned_sym->s; | ||
| 6997 | Lisp_Object val; | ||
| 6998 | Lisp_Object tem; | ||
| 6999 | |||
| 7000 | if (sblk == symbol_block && bn >= symbol_block_index) | 7038 | if (sblk == symbol_block && bn >= symbol_block_index) |
| 7001 | break; | 7039 | break; |
| 7002 | 7040 | ||
| 7003 | XSETSYMBOL (tem, sym); | 7041 | Lisp_Object sym = make_lisp_symbol (&aligned_sym->s); |
| 7004 | val = find_symbol_value (tem); | 7042 | if (symbol_uses_obj (sym, obj)) |
| 7005 | if (EQ (val, obj) | ||
| 7006 | || EQ (sym->function, obj) | ||
| 7007 | || (!NILP (sym->function) | ||
| 7008 | && COMPILEDP (sym->function) | ||
| 7009 | && EQ (AREF (sym->function, COMPILED_BYTECODE), obj)) | ||
| 7010 | || (!NILP (val) | ||
| 7011 | && COMPILEDP (val) | ||
| 7012 | && EQ (AREF (val, COMPILED_BYTECODE), obj))) | ||
| 7013 | { | 7043 | { |
| 7014 | found = Fcons (tem, found); | 7044 | found = Fcons (sym, found); |
| 7015 | if (--find_max == 0) | 7045 | if (--find_max == 0) |
| 7016 | goto out; | 7046 | goto out; |
| 7017 | } | 7047 | } |
| @@ -7154,7 +7184,9 @@ verify_alloca (void) | |||
| 7154 | void | 7184 | void |
| 7155 | init_alloc_once (void) | 7185 | init_alloc_once (void) |
| 7156 | { | 7186 | { |
| 7157 | /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ | 7187 | /* Even though Qt's contents are not set up, its address is known. */ |
| 7188 | Vpurify_flag = Qt; | ||
| 7189 | |||
| 7158 | purebeg = PUREBEG; | 7190 | purebeg = PUREBEG; |
| 7159 | pure_size = PURESIZE; | 7191 | pure_size = PURESIZE; |
| 7160 | 7192 | ||
| @@ -7230,6 +7262,7 @@ If this portion is smaller than `gc-cons-threshold', this is ignored. */); | |||
| 7230 | 7262 | ||
| 7231 | DEFVAR_INT ("symbols-consed", symbols_consed, | 7263 | DEFVAR_INT ("symbols-consed", symbols_consed, |
| 7232 | doc: /* Number of symbols that have been consed so far. */); | 7264 | doc: /* Number of symbols that have been consed so far. */); |
| 7265 | symbols_consed += ARRAYELTS (lispsym); | ||
| 7233 | 7266 | ||
| 7234 | DEFVAR_INT ("string-chars-consed", string_chars_consed, | 7267 | DEFVAR_INT ("string-chars-consed", string_chars_consed, |
| 7235 | doc: /* Number of string characters that have been consed so far. */); | 7268 | doc: /* Number of string characters that have been consed so far. */); |