diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 82 |
1 files changed, 63 insertions, 19 deletions
diff --git a/src/alloc.c b/src/alloc.c index dbd1ece5d49..ea8d81648d7 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3357,6 +3357,13 @@ struct symbol_block | |||
| 3357 | 3357 | ||
| 3358 | static struct symbol_block *symbol_block; | 3358 | static struct symbol_block *symbol_block; |
| 3359 | static int symbol_block_index = SYMBOL_BLOCK_SIZE; | 3359 | static int symbol_block_index = SYMBOL_BLOCK_SIZE; |
| 3360 | /* Pointer to the first symbol_block that contains pinned symbols. | ||
| 3361 | Tests for 24.4 showed that at dump-time, Emacs contains about 15K symbols, | ||
| 3362 | 10K of which are pinned (and all but 250 of them are interned in obarray), | ||
| 3363 | whereas a "typical session" has in the order of 30K symbols. | ||
| 3364 | `symbol_block_pinned' lets mark_pinned_symbols scan only 15K symbols rather | ||
| 3365 | than 30K to find the 10K symbols we need to mark. */ | ||
| 3366 | static struct symbol_block *symbol_block_pinned; | ||
| 3360 | 3367 | ||
| 3361 | /* List of free symbols. */ | 3368 | /* List of free symbols. */ |
| 3362 | 3369 | ||
| @@ -3409,10 +3416,11 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3409 | SET_SYMBOL_VAL (p, Qunbound); | 3416 | SET_SYMBOL_VAL (p, Qunbound); |
| 3410 | set_symbol_function (val, Qnil); | 3417 | set_symbol_function (val, Qnil); |
| 3411 | set_symbol_next (val, NULL); | 3418 | set_symbol_next (val, NULL); |
| 3412 | p->gcmarkbit = 0; | 3419 | p->gcmarkbit = false; |
| 3413 | p->interned = SYMBOL_UNINTERNED; | 3420 | p->interned = SYMBOL_UNINTERNED; |
| 3414 | p->constant = 0; | 3421 | p->constant = 0; |
| 3415 | p->declared_special = 0; | 3422 | p->declared_special = false; |
| 3423 | p->pinned = false; | ||
| 3416 | consing_since_gc += sizeof (struct Lisp_Symbol); | 3424 | consing_since_gc += sizeof (struct Lisp_Symbol); |
| 3417 | symbols_consed++; | 3425 | symbols_consed++; |
| 3418 | total_free_symbols--; | 3426 | total_free_symbols--; |
| @@ -5214,6 +5222,8 @@ make_pure_c_string (const char *data, ptrdiff_t nchars) | |||
| 5214 | return string; | 5222 | return string; |
| 5215 | } | 5223 | } |
| 5216 | 5224 | ||
| 5225 | static Lisp_Object purecopy (Lisp_Object obj); | ||
| 5226 | |||
| 5217 | /* Return a cons allocated from pure space. Give it pure copies | 5227 | /* Return a cons allocated from pure space. Give it pure copies |
| 5218 | of CAR as car and CDR as cdr. */ | 5228 | of CAR as car and CDR as cdr. */ |
| 5219 | 5229 | ||
| @@ -5223,8 +5233,8 @@ pure_cons (Lisp_Object car, Lisp_Object cdr) | |||
| 5223 | Lisp_Object new; | 5233 | Lisp_Object new; |
| 5224 | struct Lisp_Cons *p = pure_alloc (sizeof *p, Lisp_Cons); | 5234 | struct Lisp_Cons *p = pure_alloc (sizeof *p, Lisp_Cons); |
| 5225 | XSETCONS (new, p); | 5235 | XSETCONS (new, p); |
| 5226 | XSETCAR (new, Fpurecopy (car)); | 5236 | XSETCAR (new, purecopy (car)); |
| 5227 | XSETCDR (new, Fpurecopy (cdr)); | 5237 | XSETCDR (new, purecopy (cdr)); |
| 5228 | return new; | 5238 | return new; |
| 5229 | } | 5239 | } |
| 5230 | 5240 | ||
| @@ -5265,9 +5275,19 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 5265 | { | 5275 | { |
| 5266 | if (NILP (Vpurify_flag)) | 5276 | if (NILP (Vpurify_flag)) |
| 5267 | return obj; | 5277 | return obj; |
| 5268 | 5278 | else if (MARKERP (obj) || OVERLAYP (obj) | |
| 5269 | if (PURE_POINTER_P (XPNTR (obj))) | 5279 | || HASH_TABLE_P (obj) || SYMBOLP (obj)) |
| 5280 | /* Can't purify those. */ | ||
| 5270 | return obj; | 5281 | return obj; |
| 5282 | else | ||
| 5283 | return purecopy (obj); | ||
| 5284 | } | ||
| 5285 | |||
| 5286 | static Lisp_Object | ||
| 5287 | purecopy (Lisp_Object obj) | ||
| 5288 | { | ||
| 5289 | if (PURE_POINTER_P (XPNTR (obj)) || INTEGERP (obj) || SUBRP (obj)) | ||
| 5290 | return obj; /* Already pure. */ | ||
| 5271 | 5291 | ||
| 5272 | if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */ | 5292 | if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */ |
| 5273 | { | 5293 | { |
| @@ -5295,7 +5315,7 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 5295 | size &= PSEUDOVECTOR_SIZE_MASK; | 5315 | size &= PSEUDOVECTOR_SIZE_MASK; |
| 5296 | vec = XVECTOR (make_pure_vector (size)); | 5316 | vec = XVECTOR (make_pure_vector (size)); |
| 5297 | for (i = 0; i < size; i++) | 5317 | for (i = 0; i < size; i++) |
| 5298 | vec->contents[i] = Fpurecopy (AREF (obj, i)); | 5318 | vec->contents[i] = purecopy (AREF (obj, i)); |
| 5299 | if (COMPILEDP (obj)) | 5319 | if (COMPILEDP (obj)) |
| 5300 | { | 5320 | { |
| 5301 | XSETPVECTYPE (vec, PVEC_COMPILED); | 5321 | XSETPVECTYPE (vec, PVEC_COMPILED); |
| @@ -5304,11 +5324,23 @@ Does not copy symbols. Copies strings without text properties. */) | |||
| 5304 | else | 5324 | else |
| 5305 | XSETVECTOR (obj, vec); | 5325 | XSETVECTOR (obj, vec); |
| 5306 | } | 5326 | } |
| 5307 | else if (MARKERP (obj)) | 5327 | else if (SYMBOLP (obj)) |
| 5308 | error ("Attempt to copy a marker to pure storage"); | 5328 | { |
| 5329 | if (!XSYMBOL (obj)->pinned) | ||
| 5330 | { /* We can't purify them, but they appear in many pure objects. | ||
| 5331 | Mark them as `pinned' so we know to mark them at every GC cycle. */ | ||
| 5332 | XSYMBOL (obj)->pinned = true; | ||
| 5333 | symbol_block_pinned = symbol_block; | ||
| 5334 | } | ||
| 5335 | return obj; | ||
| 5336 | } | ||
| 5309 | else | 5337 | else |
| 5310 | /* Not purified, don't hash-cons. */ | 5338 | { |
| 5311 | return obj; | 5339 | Lisp_Object args[2]; |
| 5340 | args[0] = build_pure_c_string ("Don't know how to purify: %S"); | ||
| 5341 | args[1] = obj; | ||
| 5342 | Fsignal (Qerror, (Fcons (Fformat (2, args), Qnil))); | ||
| 5343 | } | ||
| 5312 | 5344 | ||
| 5313 | if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */ | 5345 | if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */ |
| 5314 | Fputhash (obj, obj, Vpurify_flag); | 5346 | Fputhash (obj, obj, Vpurify_flag); |
| @@ -5471,6 +5503,24 @@ compact_undo_list (Lisp_Object list) | |||
| 5471 | return list; | 5503 | return list; |
| 5472 | } | 5504 | } |
| 5473 | 5505 | ||
| 5506 | static void | ||
| 5507 | mark_pinned_symbols (void) | ||
| 5508 | { | ||
| 5509 | struct symbol_block *sblk; | ||
| 5510 | int lim = (symbol_block_pinned == symbol_block | ||
| 5511 | ? symbol_block_index : SYMBOL_BLOCK_SIZE); | ||
| 5512 | |||
| 5513 | for (sblk = symbol_block_pinned; sblk; sblk = sblk->next) | ||
| 5514 | { | ||
| 5515 | union aligned_Lisp_Symbol *sym = sblk->symbols, *end = sym + lim; | ||
| 5516 | for (; sym < end; ++sym) | ||
| 5517 | if (sym->s.pinned) | ||
| 5518 | mark_object (make_lisp_ptr (&sym->s, Lisp_Symbol)); | ||
| 5519 | |||
| 5520 | lim = SYMBOL_BLOCK_SIZE; | ||
| 5521 | } | ||
| 5522 | } | ||
| 5523 | |||
| 5474 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 5524 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| 5475 | doc: /* Reclaim storage for Lisp objects no longer needed. | 5525 | doc: /* Reclaim storage for Lisp objects no longer needed. |
| 5476 | Garbage collection happens automatically if you cons more than | 5526 | Garbage collection happens automatically if you cons more than |
| @@ -5573,6 +5623,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5573 | for (i = 0; i < staticidx; i++) | 5623 | for (i = 0; i < staticidx; i++) |
| 5574 | mark_object (*staticvec[i]); | 5624 | mark_object (*staticvec[i]); |
| 5575 | 5625 | ||
| 5626 | mark_pinned_symbols (); | ||
| 5576 | mark_specpdl (); | 5627 | mark_specpdl (); |
| 5577 | mark_terminals (); | 5628 | mark_terminals (); |
| 5578 | mark_kboards (); | 5629 | mark_kboards (); |
| @@ -6574,12 +6625,7 @@ sweep_symbols (void) | |||
| 6574 | 6625 | ||
| 6575 | for (; sym < end; ++sym) | 6626 | for (; sym < end; ++sym) |
| 6576 | { | 6627 | { |
| 6577 | /* Check if the symbol was created during loadup. In such a case | 6628 | if (!sym->s.gcmarkbit) |
| 6578 | it might be pointed to by pure bytecode which we don't trace, | ||
| 6579 | so we conservatively assume that it is live. */ | ||
| 6580 | bool pure_p = PURE_POINTER_P (XSTRING (sym->s.name)); | ||
| 6581 | |||
| 6582 | if (!sym->s.gcmarkbit && !pure_p) | ||
| 6583 | { | 6629 | { |
| 6584 | if (sym->s.redirect == SYMBOL_LOCALIZED) | 6630 | if (sym->s.redirect == SYMBOL_LOCALIZED) |
| 6585 | xfree (SYMBOL_BLV (&sym->s)); | 6631 | xfree (SYMBOL_BLV (&sym->s)); |
| @@ -6593,8 +6639,6 @@ sweep_symbols (void) | |||
| 6593 | else | 6639 | else |
| 6594 | { | 6640 | { |
| 6595 | ++num_used; | 6641 | ++num_used; |
| 6596 | if (!pure_p) | ||
| 6597 | eassert (!STRING_MARKED_P (XSTRING (sym->s.name))); | ||
| 6598 | sym->s.gcmarkbit = 0; | 6642 | sym->s.gcmarkbit = 0; |
| 6599 | } | 6643 | } |
| 6600 | } | 6644 | } |