]> git.eshelyaron.com Git - emacs.git/commitdiff
Discard killed buffers from deleted window and frame objects.
authorDmitry Antipov <dmantipov@yandex.ru>
Tue, 11 Sep 2012 15:42:50 +0000 (19:42 +0400)
committerDmitry Antipov <dmantipov@yandex.ru>
Tue, 11 Sep 2012 15:42:50 +0000 (19:42 +0400)
This reduces an amount of references to killed buffers and
helps GC to reclaim them faster.
* alloc.c (discard_killed_buffers): New function.
(mark_object): Use it for deleted windows and frames.
(mark_object): If symbol's value is set up for a killed buffer
or deleted frame, restore it's global binding.
* data.c (swap_in_global_binding): Add GC notice.
(swap_in_symval_forwarding): Use convenient set_blv_where.
* window.c (wset_next_buffers, wset_prev_buffers): Move ...
* window.h: ... to here.

src/ChangeLog
src/alloc.c
src/data.c
src/window.c
src/window.h

index cecd31ddab486620ac4628da5c6d4f723ec3c3fe..46f1847f7f6df2cdcf11fc18aa1d337178bc7b71 100644 (file)
@@ -1,3 +1,17 @@
+2012-09-11  Dmitry Antipov  <dmantipov@yandex.ru>
+
+       Discard killed buffers from deleted window and frame objects.
+       This reduces an amount of references to killed buffers and
+       helps GC to reclaim them faster.
+       * alloc.c (discard_killed_buffers): New function.
+       (mark_object): Use it for deleted windows and frames.
+       (mark_object): If symbol's value is set up for a killed buffer
+       or deleted frame, restore it's global binding.
+       * data.c (swap_in_global_binding): Add GC notice.
+       (swap_in_symval_forwarding): Use convenient set_blv_where.
+       * window.c (wset_next_buffers, wset_prev_buffers): Move ...
+       * window.h: ... to here.
+
 2012-09-11  Dmitry Antipov  <dmantipov@yandex.ru>
 
        Convenient macro to check whether the buffer is live.
index 7bbc0abcd9acd032bcd4afe7c2fee67a69490620..fb16b7d751182d52c8bb5ed287e26852c6800936 100644 (file)
@@ -5865,6 +5865,32 @@ mark_buffer (struct buffer *buffer)
     mark_buffer (buffer->base_buffer);
 }
 
+/* Remove killed buffers or items whose car is a killed buffer
+   from LIST and return changed LIST.  Called during GC.  */
+
+static inline Lisp_Object
+discard_killed_buffers (Lisp_Object list)
+{
+  Lisp_Object tail, prev, tem;
+
+  for (tail = list, prev = Qnil; CONSP (tail); tail = XCDR (tail))
+    {
+      tem = XCAR (tail);
+      if (CONSP (tem))
+       tem = XCAR (tem);
+      if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem)))
+       {
+         if (NILP (prev))
+           list = XCDR (tail);
+         else
+           XSETCDR (prev, XCDR (tail));
+       }
+      else
+       prev = tail;
+    }
+  return list;
+}
+
 /* Determine type of generic Lisp_Object and mark it accordingly.  */
 
 void
@@ -6001,20 +6027,41 @@ mark_object (Lisp_Object arg)
            break;
 
          case PVEC_FRAME:
-           mark_vectorlike (ptr);
-           mark_face_cache (((struct frame *) ptr)->face_cache);
+           {
+             struct frame *f = (struct frame *) ptr;
+
+             /* For live frames, killed buffers are filtered out by
+                store_frame_param.  For dead frames, we do it here in
+                attempt to help GC to reclaim killed buffers faster.  */
+             if (!FRAME_LIVE_P (f))
+               fset_buffer_list (f, discard_killed_buffers (f->buffer_list));
+
+             mark_vectorlike (ptr);
+             mark_face_cache (f->face_cache);
+           }
            break;
 
          case PVEC_WINDOW:
            {
              struct window *w = (struct window *) ptr;
+             bool leaf = NILP (w->hchild) && NILP (w->vchild);
+             
+             /* For live windows, Lisp code filters out killed buffers
+                from both buffer lists.  For dead windows, we do it here
+                in attempt to help GC to reclaim killed buffers faster.  */
+             if (leaf && NILP (w->buffer))
+               {
+                 wset_prev_buffers
+                   (w, discard_killed_buffers (w->prev_buffers));
+                 wset_next_buffers
+                   (w, discard_killed_buffers (w->next_buffers));
+               }
 
              mark_vectorlike (ptr);
              /* Mark glyphs for leaf windows.  Marking window
                 matrices is sufficient because frame matrices
                 use the same glyph memory.  */
-             if (NILP (w->hchild) && NILP (w->vchild)
-                 && w->current_matrix)
+             if (leaf && w->current_matrix)
                {
                  mark_glyph_matrix (w->current_matrix);
                  mark_glyph_matrix (w->desired_matrix);
@@ -6081,10 +6128,14 @@ mark_object (Lisp_Object arg)
          case SYMBOL_LOCALIZED:
            {
              struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
-             /* If the value is forwarded to a buffer or keyboard field,
-                these are marked when we see the corresponding object.
-                And if it's forwarded to a C variable, either it's not
-                a Lisp_Object var, or it's staticpro'd already.  */
+             Lisp_Object where = blv->where;
+             /* If the value is set up for a killed buffer or deleted
+                frame, restore it's global binding.  If the value is
+                forwarded to a C variable, either it's not a Lisp_Object
+                var, or it's staticpro'd already.  */
+             if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where)))
+                 || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where))))
+               swap_in_global_binding (ptr);
              mark_object (blv->where);
              mark_object (blv->valcell);
              mark_object (blv->defcell);
index 4678ac1208c2c7fded7a3300a3b6031431a43ba9..d894ac71a6572f9d79e4d02afc5e07ef4b3033c1 100644 (file)
@@ -948,8 +948,10 @@ store_symval_forwarding (union Lisp_Fwd *valcontents, register Lisp_Object newva
     }
 }
 
-/* Set up SYMBOL to refer to its global binding.
-   This makes it safe to alter the status of other bindings.  */
+/* Set up SYMBOL to refer to its global binding.  This makes it safe
+   to alter the status of other bindings.  BEWARE: this may be called
+   during the mark phase of GC, where we assume that Lisp_Object slots
+   of BLV are marked after this function has changed them.  */
 
 void
 swap_in_global_binding (struct Lisp_Symbol *symbol)
@@ -1008,7 +1010,7 @@ swap_in_symval_forwarding (struct Lisp_Symbol *symbol, struct Lisp_Buffer_Local_
        else
          {
            tem1 = assq_no_quit (var, BVAR (current_buffer, local_var_alist));
-           XSETBUFFER (blv->where, current_buffer);
+           set_blv_where (blv, Fcurrent_buffer ());
          }
       }
       if (!(blv->found = !NILP (tem1)))
index 4a833a120b3c8a3924437637dbb0ca379bc6ce18..18a550782e8ee8b4e9ac2083582aafd0c5ebcb5d 100644 (file)
@@ -176,11 +176,6 @@ wset_new_total (struct window *w, Lisp_Object val)
   w->new_total = val;
 }
 static inline void
-wset_next_buffers (struct window *w, Lisp_Object val)
-{
-  w->next_buffers = val;
-}
-static inline void
 wset_normal_cols (struct window *w, Lisp_Object val)
 {
   w->normal_cols = val;
@@ -201,11 +196,6 @@ wset_pointm (struct window *w, Lisp_Object val)
   w->pointm = val;
 }
 static inline void
-wset_prev_buffers (struct window *w, Lisp_Object val)
-{
-  w->prev_buffers = val;
-}
-static inline void
 wset_right_fringe_width (struct window *w, Lisp_Object val)
 {
   w->right_fringe_width = val;
index a70bc55bac50e5b004ce09743d60023abfd19f7b..62ae43a999d83326c30de060eb4197f3bdeb04f5 100644 (file)
@@ -414,7 +414,16 @@ wset_window_end_vpos (struct window *w, Lisp_Object val)
 {
   w->window_end_vpos = val;
 }
-
+WINDOW_INLINE void
+wset_prev_buffers (struct window *w, Lisp_Object val)
+{
+  w->prev_buffers = val;
+}
+WINDOW_INLINE void
+wset_next_buffers (struct window *w, Lisp_Object val)
+{
+  w->next_buffers = val;
+}
 
 /* 1 if W is a minibuffer window.  */