aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorDmitry Antipov2013-10-21 18:11:25 +0400
committerDmitry Antipov2013-10-21 18:11:25 +0400
commitfc54bdd59909d87c56686a42aba3b92785617a51 (patch)
tree676fd033b56d0a4a72cb9c8e8576a76f3fce2945 /src/alloc.c
parentdf74c4be16efb83408b78c5b1205fccfb2c10696 (diff)
downloademacs-fc54bdd59909d87c56686a42aba3b92785617a51.tar.gz
emacs-fc54bdd59909d87c56686a42aba3b92785617a51.zip
Do not allow font caches to grow too large.
* alloc.c (compact_font_cache_entry, compact_font_caches): New functions or stub if not HAVE_WINDOW_SYSTEM. (compact_undo_list): Factor out from Fgarbage_collect. Add comment. (mark_face_cache): Mark face font. Move down to avoid extra prototypes. (mark_terminals): Do not mark font cache here. (Fgarbage_collect): Call compaction functions described above. Adjust comment.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c189
1 files changed, 124 insertions, 65 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 02deaa94af1..2c28b5df6d7 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5254,6 +5254,95 @@ total_bytes_of_live_objects (void)
5254 return tot; 5254 return tot;
5255} 5255}
5256 5256
5257#ifdef HAVE_WINDOW_SYSTEM
5258
5259/* Remove unmarked font-spec and font-entity objects from ENTRY, which is
5260 (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...), and return changed entry. */
5261
5262static Lisp_Object
5263compact_font_cache_entry (Lisp_Object entry)
5264{
5265 Lisp_Object tail, *prev = &entry;
5266
5267 for (tail = entry; CONSP (tail); tail = XCDR (tail))
5268 {
5269 bool drop = 0;
5270 Lisp_Object obj = XCAR (tail);
5271
5272 /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]). */
5273 if (CONSP (obj) && FONT_SPEC_P (XCAR (obj))
5274 && !VECTOR_MARKED_P (XFONT_SPEC (XCAR (obj)))
5275 && VECTORP (XCDR (obj)))
5276 {
5277 ptrdiff_t i, size = ASIZE (XCDR (obj)) & ~ARRAY_MARK_FLAG;
5278
5279 /* If font-spec is not marked, most likely all font-entities
5280 are not marked too. But we must be sure that nothing is
5281 marked within OBJ before we really drop it. */
5282 for (i = 0; i < size; i++)
5283 if (VECTOR_MARKED_P (XFONT_ENTITY (AREF (XCDR (obj), i))))
5284 break;
5285
5286 if (i == size)
5287 drop = 1;
5288 }
5289 if (drop)
5290 *prev = XCDR (tail);
5291 else
5292 prev = xcdr_addr (tail);
5293 }
5294 return entry;
5295}
5296
5297/* Compact font caches on all terminals and mark
5298 everything which is still here after compaction. */
5299
5300static void
5301compact_font_caches (void)
5302{
5303 struct terminal *t;
5304
5305 for (t = terminal_list; t; t = t->next_terminal)
5306 {
5307 Lisp_Object cache = TERMINAL_FONT_CACHE (t);
5308
5309 if (CONSP (cache))
5310 {
5311 Lisp_Object entry;
5312
5313 for (entry = XCDR (cache); CONSP (entry); entry = XCDR (entry))
5314 XSETCAR (entry, compact_font_cache_entry (XCAR (entry)));
5315 }
5316 mark_object (cache);
5317 }
5318}
5319
5320#else /* not HAVE_WINDOW_SYSTEM */
5321
5322#define compact_font_caches() (void)(0)
5323
5324#endif /* HAVE_WINDOW_SYSTEM */
5325
5326/* Remove (MARKER . DATA) entries with unmarked MARKER
5327 from buffer undo LIST and return changed list. */
5328
5329static Lisp_Object
5330compact_undo_list (Lisp_Object list)
5331{
5332 Lisp_Object tail, *prev = &list;
5333
5334 for (tail = list; CONSP (tail); tail = XCDR (tail))
5335 {
5336 if (CONSP (XCAR (tail))
5337 && MARKERP (XCAR (XCAR (tail)))
5338 && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit)
5339 *prev = XCDR (tail);
5340 else
5341 prev = xcdr_addr (tail);
5342 }
5343 return list;
5344}
5345
5257DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", 5346DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
5258 doc: /* Reclaim storage for Lisp objects no longer needed. 5347 doc: /* Reclaim storage for Lisp objects no longer needed.
5259Garbage collection happens automatically if you cons more than 5348Garbage collection happens automatically if you cons more than
@@ -5392,46 +5481,19 @@ See Info node `(elisp)Garbage Collection'. */)
5392 mark_stack (); 5481 mark_stack ();
5393#endif 5482#endif
5394 5483
5395 /* Everything is now marked, except for the things that require special 5484 /* Everything is now marked, except for the data in font caches
5396 finalization, i.e. the undo_list. 5485 and undo lists. They're compacted by removing an items which
5397 Look thru every buffer's undo list 5486 aren't reachable otherwise. */
5398 for elements that update markers that were not marked, 5487
5399 and delete them. */ 5488 compact_font_caches ();
5489
5400 FOR_EACH_BUFFER (nextb) 5490 FOR_EACH_BUFFER (nextb)
5401 { 5491 {
5402 /* If a buffer's undo list is Qt, that means that undo is 5492 if (!EQ (BVAR (nextb, undo_list), Qt))
5403 turned off in that buffer. Calling truncate_undo_list on 5493 bset_undo_list (nextb, compact_undo_list (BVAR (nextb, undo_list)));
5404 Qt tends to return NULL, which effectively turns undo back on. 5494 /* Now that we have stripped the elements that need not be
5405 So don't call truncate_undo_list if undo_list is Qt. */ 5495 in the undo_list any more, we can finally mark the list. */
5406 if (! EQ (nextb->INTERNAL_FIELD (undo_list), Qt)) 5496 mark_object (BVAR (nextb, undo_list));
5407 {
5408 Lisp_Object tail, prev;
5409 tail = nextb->INTERNAL_FIELD (undo_list);
5410 prev = Qnil;
5411 while (CONSP (tail))
5412 {
5413 if (CONSP (XCAR (tail))
5414 && MARKERP (XCAR (XCAR (tail)))
5415 && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit)
5416 {
5417 if (NILP (prev))
5418 nextb->INTERNAL_FIELD (undo_list) = tail = XCDR (tail);
5419 else
5420 {
5421 tail = XCDR (tail);
5422 XSETCDR (prev, tail);
5423 }
5424 }
5425 else
5426 {
5427 prev = tail;
5428 tail = XCDR (tail);
5429 }
5430 }
5431 }
5432 /* Now that we have stripped the elements that need not be in the
5433 undo_list any more, we can finally mark the list. */
5434 mark_object (nextb->INTERNAL_FIELD (undo_list));
5435 } 5497 }
5436 5498
5437 gc_sweep (); 5499 gc_sweep ();
@@ -5603,30 +5665,6 @@ mark_glyph_matrix (struct glyph_matrix *matrix)
5603 } 5665 }
5604} 5666}
5605 5667
5606
5607/* Mark Lisp faces in the face cache C. */
5608
5609static void
5610mark_face_cache (struct face_cache *c)
5611{
5612 if (c)
5613 {
5614 int i, j;
5615 for (i = 0; i < c->used; ++i)
5616 {
5617 struct face *face = FACE_FROM_ID (c->f, i);
5618
5619 if (face)
5620 {
5621 for (j = 0; j < LFACE_VECTOR_SIZE; ++j)
5622 mark_object (face->lface[j]);
5623 }
5624 }
5625 }
5626}
5627
5628
5629
5630/* Mark reference to a Lisp_Object. 5668/* Mark reference to a Lisp_Object.
5631 If the object referred to has not been seen yet, recursively mark 5669 If the object referred to has not been seen yet, recursively mark
5632 all the references contained in it. */ 5670 all the references contained in it. */
@@ -5726,6 +5764,30 @@ mark_buffer (struct buffer *buffer)
5726 mark_buffer (buffer->base_buffer); 5764 mark_buffer (buffer->base_buffer);
5727} 5765}
5728 5766
5767/* Mark Lisp faces in the face cache C. */
5768
5769static void
5770mark_face_cache (struct face_cache *c)
5771{
5772 if (c)
5773 {
5774 int i, j;
5775 for (i = 0; i < c->used; ++i)
5776 {
5777 struct face *face = FACE_FROM_ID (c->f, i);
5778
5779 if (face)
5780 {
5781 if (face->font && !VECTOR_MARKED_P (face->font))
5782 mark_vectorlike ((struct Lisp_Vector *) face->font);
5783
5784 for (j = 0; j < LFACE_VECTOR_SIZE; ++j)
5785 mark_object (face->lface[j]);
5786 }
5787 }
5788 }
5789}
5790
5729/* Remove killed buffers or items whose car is a killed buffer from 5791/* Remove killed buffers or items whose car is a killed buffer from
5730 LIST, and mark other items. Return changed LIST, which is marked. */ 5792 LIST, and mark other items. Return changed LIST, which is marked. */
5731 5793
@@ -6118,9 +6180,6 @@ mark_terminals (void)
6118 it might have been marked already. Make sure the image cache 6180 it might have been marked already. Make sure the image cache
6119 gets marked. */ 6181 gets marked. */
6120 mark_image_cache (t->image_cache); 6182 mark_image_cache (t->image_cache);
6121 /* FIXME: currently font cache may grow too large
6122 and probably needs special finalization. */
6123 mark_object (TERMINAL_FONT_CACHE (t));
6124#endif /* HAVE_WINDOW_SYSTEM */ 6183#endif /* HAVE_WINDOW_SYSTEM */
6125 if (!VECTOR_MARKED_P (t)) 6184 if (!VECTOR_MARKED_P (t))
6126 mark_vectorlike ((struct Lisp_Vector *)t); 6185 mark_vectorlike ((struct Lisp_Vector *)t);