From: Dmitry Antipov Date: Tue, 11 Sep 2012 15:42:50 +0000 (+0400) Subject: Discard killed buffers from deleted window and frame objects. X-Git-Tag: emacs-24.2.90~320 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=d73e321cc241c0029e6874501cf32ee63643825c;p=emacs.git 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. --- diff --git a/src/ChangeLog b/src/ChangeLog index cecd31ddab4..46f1847f7f6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,17 @@ +2012-09-11 Dmitry Antipov + + 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 Convenient macro to check whether the buffer is live. diff --git a/src/alloc.c b/src/alloc.c index 7bbc0abcd9a..fb16b7d7511 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -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); diff --git a/src/data.c b/src/data.c index 4678ac1208c..d894ac71a65 100644 --- a/src/data.c +++ b/src/data.c @@ -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))) diff --git a/src/window.c b/src/window.c index 4a833a120b3..18a550782e8 100644 --- a/src/window.c +++ b/src/window.c @@ -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; diff --git a/src/window.h b/src/window.h index a70bc55bac5..62ae43a999d 100644 --- a/src/window.h +++ b/src/window.h @@ -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. */