diff options
| author | Dmitry Antipov | 2013-10-21 18:11:25 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2013-10-21 18:11:25 +0400 |
| commit | fc54bdd59909d87c56686a42aba3b92785617a51 (patch) | |
| tree | 676fd033b56d0a4a72cb9c8e8576a76f3fce2945 /src/alloc.c | |
| parent | df74c4be16efb83408b78c5b1205fccfb2c10696 (diff) | |
| download | emacs-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.c | 189 |
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 | |||
| 5262 | static Lisp_Object | ||
| 5263 | compact_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 | |||
| 5300 | static void | ||
| 5301 | compact_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 | |||
| 5329 | static Lisp_Object | ||
| 5330 | compact_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 | |||
| 5257 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 5346 | DEFUN ("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. |
| 5259 | Garbage collection happens automatically if you cons more than | 5348 | Garbage 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 | |||
| 5609 | static void | ||
| 5610 | mark_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 | |||
| 5769 | static void | ||
| 5770 | mark_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); |