aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorStefan Monnier2014-04-07 12:08:46 -0400
committerStefan Monnier2014-04-07 12:08:46 -0400
commite3b838807bf9fbbbec9826de6c1e4efdf72acb78 (patch)
treeaf955b069b9dab5d52cfed618cf1f2f7cffa40f5 /src/alloc.c
parent190f899aed4eeb62286874bda47a92236d52ad4c (diff)
downloademacs-e3b838807bf9fbbbec9826de6c1e4efdf72acb78.tar.gz
emacs-e3b838807bf9fbbbec9826de6c1e4efdf72acb78.zip
* src/alloc.c: Keep track of symbols referenced from pure space (bug#17168).
(symbol_block_pinned): New var. (Fmake_symbol): Initialize `pinned'. (purecopy): New function, extracted from Fpurecopy. Mark symbols as pinned and signal an error for un-purifiable objects. (pure_cons): Use it. (Fpurecopy): Use it, except for objects that can't be purified. (mark_pinned_symbols): New function. (Fgarbage_collect): Use it. (gc_sweep): Remove hack made unnecessary. * src/lisp.h (struct Lisp_Symbol): New bitfield `pinned'.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c83
1 files changed, 64 insertions, 19 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 62c3beec1d2..d4e24b6244b 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3316,6 +3316,13 @@ struct symbol_block
3316 3316
3317static struct symbol_block *symbol_block; 3317static struct symbol_block *symbol_block;
3318static int symbol_block_index = SYMBOL_BLOCK_SIZE; 3318static int symbol_block_index = SYMBOL_BLOCK_SIZE;
3319/* Pointer to the first symbol_block that contains pinned symbols.
3320 Tests for 24.4 showed that at dump-time, Emacs contains about 15K symbols,
3321 10K of which are pinned (and all but 250 of them are interned in obarray),
3322 whereas a "typical session" has in the order of 30K symbols.
3323 `symbol_block_pinned' lets mark_pinned_symbols scan only 15K symbols rather
3324 than 30K to find the 10K symbols we need to mark. */
3325static struct symbol_block *symbol_block_pinned;
3319 3326
3320/* List of free symbols. */ 3327/* List of free symbols. */
3321 3328
@@ -3368,10 +3375,11 @@ Its value is void, and its function definition and property list are nil. */)
3368 SET_SYMBOL_VAL (p, Qunbound); 3375 SET_SYMBOL_VAL (p, Qunbound);
3369 set_symbol_function (val, Qnil); 3376 set_symbol_function (val, Qnil);
3370 set_symbol_next (val, NULL); 3377 set_symbol_next (val, NULL);
3371 p->gcmarkbit = 0; 3378 p->gcmarkbit = false;
3372 p->interned = SYMBOL_UNINTERNED; 3379 p->interned = SYMBOL_UNINTERNED;
3373 p->constant = 0; 3380 p->constant = 0;
3374 p->declared_special = 0; 3381 p->declared_special = false;
3382 p->pinned = false;
3375 consing_since_gc += sizeof (struct Lisp_Symbol); 3383 consing_since_gc += sizeof (struct Lisp_Symbol);
3376 symbols_consed++; 3384 symbols_consed++;
3377 total_free_symbols--; 3385 total_free_symbols--;
@@ -5173,6 +5181,8 @@ make_pure_c_string (const char *data, ptrdiff_t nchars)
5173 return string; 5181 return string;
5174} 5182}
5175 5183
5184static Lisp_Object purecopy (Lisp_Object obj);
5185
5176/* Return a cons allocated from pure space. Give it pure copies 5186/* Return a cons allocated from pure space. Give it pure copies
5177 of CAR as car and CDR as cdr. */ 5187 of CAR as car and CDR as cdr. */
5178 5188
@@ -5182,8 +5192,8 @@ pure_cons (Lisp_Object car, Lisp_Object cdr)
5182 Lisp_Object new; 5192 Lisp_Object new;
5183 struct Lisp_Cons *p = pure_alloc (sizeof *p, Lisp_Cons); 5193 struct Lisp_Cons *p = pure_alloc (sizeof *p, Lisp_Cons);
5184 XSETCONS (new, p); 5194 XSETCONS (new, p);
5185 XSETCAR (new, Fpurecopy (car)); 5195 XSETCAR (new, purecopy (car));
5186 XSETCDR (new, Fpurecopy (cdr)); 5196 XSETCDR (new, purecopy (cdr));
5187 return new; 5197 return new;
5188} 5198}
5189 5199
@@ -5224,9 +5234,19 @@ Does not copy symbols. Copies strings without text properties. */)
5224{ 5234{
5225 if (NILP (Vpurify_flag)) 5235 if (NILP (Vpurify_flag))
5226 return obj; 5236 return obj;
5227 5237 else if (MARKERP (obj) || OVERLAYP (obj)
5228 if (PURE_POINTER_P (XPNTR (obj))) 5238 || HASH_TABLE_P (obj) || SYMBOLP (obj))
5239 /* Can't purify those. */
5229 return obj; 5240 return obj;
5241 else
5242 return purecopy (obj);
5243}
5244
5245static Lisp_Object
5246purecopy (Lisp_Object obj)
5247{
5248 if (PURE_POINTER_P (XPNTR (obj)) || INTEGERP (obj) || SUBRP (obj))
5249 return obj; /* Already pure. */
5230 5250
5231 if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */ 5251 if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */
5232 { 5252 {
@@ -5254,7 +5274,7 @@ Does not copy symbols. Copies strings without text properties. */)
5254 size &= PSEUDOVECTOR_SIZE_MASK; 5274 size &= PSEUDOVECTOR_SIZE_MASK;
5255 vec = XVECTOR (make_pure_vector (size)); 5275 vec = XVECTOR (make_pure_vector (size));
5256 for (i = 0; i < size; i++) 5276 for (i = 0; i < size; i++)
5257 vec->contents[i] = Fpurecopy (AREF (obj, i)); 5277 vec->contents[i] = purecopy (AREF (obj, i));
5258 if (COMPILEDP (obj)) 5278 if (COMPILEDP (obj))
5259 { 5279 {
5260 XSETPVECTYPE (vec, PVEC_COMPILED); 5280 XSETPVECTYPE (vec, PVEC_COMPILED);
@@ -5263,11 +5283,23 @@ Does not copy symbols. Copies strings without text properties. */)
5263 else 5283 else
5264 XSETVECTOR (obj, vec); 5284 XSETVECTOR (obj, vec);
5265 } 5285 }
5266 else if (MARKERP (obj)) 5286 else if (SYMBOLP (obj))
5267 error ("Attempt to copy a marker to pure storage"); 5287 {
5288 if (!XSYMBOL (obj)->pinned)
5289 { /* We can't purify them, but they appear in many pure objects.
5290 Mark them as `pinned' so we know to mark them at every GC cycle. */
5291 XSYMBOL (obj)->pinned = true;
5292 symbol_block_pinned = symbol_block;
5293 }
5294 return obj;
5295 }
5268 else 5296 else
5269 /* Not purified, don't hash-cons. */ 5297 {
5270 return obj; 5298 Lisp_Object args[2];
5299 args[0] = build_pure_c_string ("Don't know how to purify: %S");
5300 args[1] = obj;
5301 Fsignal (Qerror, (Fcons (Fformat (2, args), Qnil)));
5302 }
5271 5303
5272 if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */ 5304 if (HASH_TABLE_P (Vpurify_flag)) /* Hash consing. */
5273 Fputhash (obj, obj, Vpurify_flag); 5305 Fputhash (obj, obj, Vpurify_flag);
@@ -5430,6 +5462,24 @@ compact_undo_list (Lisp_Object list)
5430 return list; 5462 return list;
5431} 5463}
5432 5464
5465static void
5466mark_pinned_symbols (void)
5467{
5468 struct symbol_block *sblk;
5469 int lim = (symbol_block_pinned == symbol_block
5470 ? symbol_block_index : SYMBOL_BLOCK_SIZE);
5471
5472 for (sblk = symbol_block_pinned; sblk; sblk = sblk->next)
5473 {
5474 union aligned_Lisp_Symbol *sym = sblk->symbols, *end = sym + lim;
5475 for (; sym < end; ++sym)
5476 if (sym->s.pinned)
5477 mark_object (make_lisp_ptr (&sym->s, Lisp_Symbol));
5478
5479 lim = SYMBOL_BLOCK_SIZE;
5480 }
5481}
5482
5433DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", 5483DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
5434 doc: /* Reclaim storage for Lisp objects no longer needed. 5484 doc: /* Reclaim storage for Lisp objects no longer needed.
5435Garbage collection happens automatically if you cons more than 5485Garbage collection happens automatically if you cons more than
@@ -5532,6 +5582,7 @@ See Info node `(elisp)Garbage Collection'. */)
5532 for (i = 0; i < staticidx; i++) 5582 for (i = 0; i < staticidx; i++)
5533 mark_object (*staticvec[i]); 5583 mark_object (*staticvec[i]);
5534 5584
5585 mark_pinned_symbols ();
5535 mark_specpdl (); 5586 mark_specpdl ();
5536 mark_terminals (); 5587 mark_terminals ();
5537 mark_kboards (); 5588 mark_kboards ();
@@ -6536,12 +6587,7 @@ gc_sweep (void)
6536 6587
6537 for (; sym < end; ++sym) 6588 for (; sym < end; ++sym)
6538 { 6589 {
6539 /* Check if the symbol was created during loadup. In such a case 6590 if (!sym->s.gcmarkbit)
6540 it might be pointed to by pure bytecode which we don't trace,
6541 so we conservatively assume that it is live. */
6542 bool pure_p = PURE_POINTER_P (XSTRING (sym->s.name));
6543
6544 if (!sym->s.gcmarkbit && !pure_p)
6545 { 6591 {
6546 if (sym->s.redirect == SYMBOL_LOCALIZED) 6592 if (sym->s.redirect == SYMBOL_LOCALIZED)
6547 xfree (SYMBOL_BLV (&sym->s)); 6593 xfree (SYMBOL_BLV (&sym->s));
@@ -6555,8 +6601,7 @@ gc_sweep (void)
6555 else 6601 else
6556 { 6602 {
6557 ++num_used; 6603 ++num_used;
6558 if (!pure_p) 6604 eassert (!STRING_MARKED_P (XSTRING (sym->s.name)));
6559 eassert (!STRING_MARKED_P (XSTRING (sym->s.name)));
6560 sym->s.gcmarkbit = 0; 6605 sym->s.gcmarkbit = 0;
6561 } 6606 }
6562 } 6607 }