+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.
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
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);
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);
}
}
-/* 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)
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)))