mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-18 20:00:36 -08:00
* src/alloc.c: Avoid O(N²) complexity when unchaining markers (bug#24548).
Unchain all dead markers with a single scan of the markers list, instead of calling the O(N) 'unchain_marker' N times. (unchain_dead_markers): New function. (sweep_buffers): Use it. (gc_sweep): Sweep buffers before markers. (sweep_misc): Check that markers have been unchained when reclaiming them.
This commit is contained in:
parent
6695c1be51
commit
cf3164523b
1 changed files with 22 additions and 2 deletions
24
src/alloc.c
24
src/alloc.c
|
|
@ -7095,7 +7095,9 @@ sweep_misc (void)
|
||||||
if (!mblk->markers[i].m.u_any.gcmarkbit)
|
if (!mblk->markers[i].m.u_any.gcmarkbit)
|
||||||
{
|
{
|
||||||
if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker)
|
if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker)
|
||||||
unchain_marker (&mblk->markers[i].m.u_marker);
|
/* Make sure markers have been unchained from their buffer
|
||||||
|
in sweep_buffer before we collect them. */
|
||||||
|
eassert (!mblk->markers[i].m.u_marker.buffer);
|
||||||
else if (mblk->markers[i].m.u_any.type == Lisp_Misc_Finalizer)
|
else if (mblk->markers[i].m.u_any.type == Lisp_Misc_Finalizer)
|
||||||
unchain_finalizer (&mblk->markers[i].m.u_finalizer);
|
unchain_finalizer (&mblk->markers[i].m.u_finalizer);
|
||||||
#ifdef HAVE_MODULES
|
#ifdef HAVE_MODULES
|
||||||
|
|
@ -7142,6 +7144,23 @@ sweep_misc (void)
|
||||||
total_free_markers = num_free;
|
total_free_markers = num_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove BUFFER's markers that are due to be swept. This is needed since
|
||||||
|
we treat BUF_MARKERS and markers's `next' field as weak pointers. */
|
||||||
|
static void
|
||||||
|
unchain_dead_markers (struct buffer *buffer)
|
||||||
|
{
|
||||||
|
struct Lisp_Marker *this, **prev = &BUF_MARKERS (buffer);
|
||||||
|
|
||||||
|
while ((this = *prev))
|
||||||
|
if (this->gcmarkbit)
|
||||||
|
prev = &this->next;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->buffer = NULL;
|
||||||
|
*prev = this->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NO_INLINE /* For better stack traces */
|
NO_INLINE /* For better stack traces */
|
||||||
static void
|
static void
|
||||||
sweep_buffers (void)
|
sweep_buffers (void)
|
||||||
|
|
@ -7160,6 +7179,7 @@ sweep_buffers (void)
|
||||||
VECTOR_UNMARK (buffer);
|
VECTOR_UNMARK (buffer);
|
||||||
/* Do not use buffer_(set|get)_intervals here. */
|
/* Do not use buffer_(set|get)_intervals here. */
|
||||||
buffer->text->intervals = balance_intervals (buffer->text->intervals);
|
buffer->text->intervals = balance_intervals (buffer->text->intervals);
|
||||||
|
unchain_dead_markers (buffer);
|
||||||
total_buffers++;
|
total_buffers++;
|
||||||
bprev = &buffer->next;
|
bprev = &buffer->next;
|
||||||
}
|
}
|
||||||
|
|
@ -7179,8 +7199,8 @@ gc_sweep (void)
|
||||||
sweep_floats ();
|
sweep_floats ();
|
||||||
sweep_intervals ();
|
sweep_intervals ();
|
||||||
sweep_symbols ();
|
sweep_symbols ();
|
||||||
sweep_misc ();
|
|
||||||
sweep_buffers ();
|
sweep_buffers ();
|
||||||
|
sweep_misc ();
|
||||||
sweep_vectors ();
|
sweep_vectors ();
|
||||||
check_string_bytes (!noninteractive);
|
check_string_bytes (!noninteractive);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue