=== modified file 'src/alloc.c' --- src/alloc.c 2013-12-09 08:23:01 +0000 +++ src/alloc.c 2013-12-11 05:38:41 +0000 @@ -5299,17 +5299,22 @@ #ifdef HAVE_WINDOW_SYSTEM +/* Rather arbitrary but willing to fix Bug#15876. */ + +#define FONT_CACHE_THRESHOLD 4096 + /* Remove unmarked font-spec and font-entity objects from ENTRY, which is (DRIVER-TYPE NUM-FRAMES FONT-CACHE-DATA ...), and return changed entry. */ static Lisp_Object -compact_font_cache_entry (Lisp_Object entry) +compact_font_cache_entry (struct terminal *t, Lisp_Object entry) { Lisp_Object tail, *prev = &entry; for (tail = entry; CONSP (tail); tail = XCDR (tail)) { bool drop = 0; + ptrdiff_t size = 0; Lisp_Object obj = XCAR (tail); /* Consider OBJ if it is (font-spec . [font-entity font-entity ...]). */ @@ -5317,8 +5322,9 @@ && !VECTOR_MARKED_P (XFONT_SPEC (XCAR (obj))) && VECTORP (XCDR (obj))) { - ptrdiff_t i, size = ASIZE (XCDR (obj)) & ~ARRAY_MARK_FLAG; + ptrdiff_t i; + size = ASIZE (XCDR (obj)) & ~ARRAY_MARK_FLAG; /* If font-spec is not marked, most likely all font-entities are not marked too. But we must be sure that nothing is marked within OBJ before we really drop it. */ @@ -5330,7 +5336,11 @@ drop = 1; } if (drop) - *prev = XCDR (tail); + { + *prev = XCDR (tail); + /* Count font-spec and vector of font-entities. */ + FONT_CACHE_SIZE (t) -= (size + 1); + } else prev = xcdr_addr (tail); } @@ -5351,10 +5361,20 @@ if (CONSP (cache)) { - Lisp_Object entry; + eassert (FONT_CACHE_SIZE (t) >= 0); + if (FONT_CACHE_SIZE (t) > FONT_CACHE_THRESHOLD) + { + Lisp_Object entry; - for (entry = XCDR (cache); CONSP (entry); entry = XCDR (entry)) - XSETCAR (entry, compact_font_cache_entry (XCAR (entry))); + fprintf (stderr, "GC%ld: font cache compaction %ld -> ", + gcs_done, FONT_CACHE_SIZE (t)); + for (entry = XCDR (cache); CONSP (entry); entry = XCDR (entry)) + XSETCAR (entry, compact_font_cache_entry (t, XCAR (entry))); + fprintf (stderr, "%ld\n", FONT_CACHE_SIZE (t)); + } + else + fprintf (stderr, "GC%ld: font cache too small (%d <= %d)\n", + gcs_done, FONT_CACHE_SIZE (t), FONT_CACHE_THRESHOLD); } mark_object (cache); } === modified file 'src/font.c' --- src/font.c 2013-12-10 03:36:36 +0000 +++ src/font.c 2013-12-11 05:35:25 +0000 @@ -2740,6 +2740,8 @@ copy = copy_font_spec (scratch_font_spec); ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache))); + /* Count font-spec and a vector of font-entities. */ + FONT_CACHE_SIZE (f->terminal) += ASIZE (val) + 1; } if (ASIZE (val) > 0 && (need_filtering @@ -2793,6 +2795,8 @@ copy = copy_font_spec (work); ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); XSETCDR (cache, Fcons (Fcons (copy, entity), XCDR (cache))); + /* Count font-spec and entity. */ + FONT_CACHE_SIZE (f->terminal) += 2; } if (! NILP (entity)) break; === modified file 'src/nsterm.h' --- src/nsterm.h 2013-12-07 16:48:12 +0000 +++ src/nsterm.h 2013-12-11 05:35:25 +0000 @@ -560,6 +560,9 @@ /* This is a cons cell of the form (NAME . FONT-LIST-CACHE). */ Lisp_Object name_list_element; + /* Amount of font-entities and font-specs objects in the cache above. */ + ptrdiff_t font_cache_size; + /* The number of fonts loaded. */ int n_fonts; === modified file 'src/termhooks.h' --- src/termhooks.h 2013-10-18 12:57:44 +0000 +++ src/termhooks.h 2013-12-11 05:35:25 +0000 @@ -628,12 +628,15 @@ #if defined (HAVE_X_WINDOWS) #define TERMINAL_FONT_CACHE(t) \ (t->type == output_x_window ? t->display_info.x->name_list_element : Qnil) +#define FONT_CACHE_SIZE(t) (t)->display_info.x->font_cache_size #elif defined (HAVE_NTGUI) #define TERMINAL_FONT_CACHE(t) \ (t->type == output_w32 ? t->display_info.w32->name_list_element : Qnil) +#define FONT_CACHE_SIZE(t) (t)->display_info.w32->font_cache_size #elif defined (HAVE_NS) #define TERMINAL_FONT_CACHE(t) \ (t->type == output_ns ? t->display_info.ns->name_list_element : Qnil) +#define FONT_CACHE_SIZE(t) (t)->display_info.ns->font_cache_size #endif extern struct terminal *get_terminal (Lisp_Object terminal, bool); === modified file 'src/w32term.h' --- src/w32term.h 2013-12-02 13:35:53 +0000 +++ src/w32term.h 2013-12-11 05:35:25 +0000 @@ -74,6 +74,9 @@ /* This is a cons cell of the form (NAME . FONT-LIST-CACHE). */ Lisp_Object name_list_element; + /* Amount of font-entities and font-specs objects in the cache above. */ + ptrdiff_t font_cache_size; + /* Number of frames that are on this display. */ int reference_count; === modified file 'src/xterm.h' --- src/xterm.h 2013-12-07 23:04:10 +0000 +++ src/xterm.h 2013-12-11 05:35:25 +0000 @@ -140,6 +140,9 @@ /* This is a cons cell of the form (NAME . FONT-LIST-CACHE). */ Lisp_Object name_list_element; + /* Amount of font-entities and font-specs objects in the cache above. */ + ptrdiff_t font_cache_size; + /* Number of frames that are on this display. */ int reference_count;