Commit d73e321c authored by Dmitry Antipov's avatar 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.
parent 96d03571
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.
......
......@@ -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);
......
......@@ -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)))
......
......@@ -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;
......
......@@ -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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment