aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c82
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
3358static struct symbol_block *symbol_block; 3358static struct symbol_block *symbol_block;
3359static int symbol_block_index = SYMBOL_BLOCK_SIZE; 3359static 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. */
3366static 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
5225static 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
5286static Lisp_Object
5287purecopy (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
5506static void
5507mark_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
5474DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", 5524DEFUN ("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.
5476Garbage collection happens automatically if you cons more than 5526Garbage 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 }