From: Dmitry Antipov Date: Fri, 20 Jul 2012 16:05:47 +0000 (+0400) Subject: Add indirection counting to speed up Fkill_buffer. X-Git-Tag: emacs-24.2.90~1118 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=9928463dcdb0164477785e83406602065de79ef8;p=emacs.git Add indirection counting to speed up Fkill_buffer. * buffer.h (struct buffer): New member. * buffer.c (Fget_buffer_create): Set indirection counter to 0. (Fmake_indirect_buffer): Set indirection counter to -1, increment base buffer indirection counter. (compact_buffer): If ENABLE_CHECKING, verify indirection counters. (Fkill_buffer): Adjust indirection counters as needed, don't walk through buffer list if indirection counter is 0. --- diff --git a/src/ChangeLog b/src/ChangeLog index d7d02a2262a..e90e48ee9dc 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2012-07-20 Dmitry Antipov + + Add indirection counting to speed up Fkill_buffer. + * buffer.h (struct buffer): New member. + * buffer.c (Fget_buffer_create): Set indirection counter to 0. + (Fmake_indirect_buffer): Set indirection counter to -1, increment + base buffer indirection counter. + (compact_buffer): If ENABLE_CHECKING, verify indirection counters. + (Fkill_buffer): Adjust indirection counters as needed, don't walk + through buffer list if indirection counter is 0. + 2012-07-20 Dmitry Antipov Extend the value returned by Fgarbage_collect with heap statistics. diff --git a/src/buffer.c b/src/buffer.c index b722ff135dd..5f9f6a79b67 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -329,7 +329,9 @@ even if it is dead. The return value is never nil. */) /* An ordinary buffer uses its own struct buffer_text. */ b->text = &b->own_text; - b->base_buffer = 0; + b->base_buffer = NULL; + /* No one shares the text with us now. */ + b->indirections = 0; BUF_GAP_SIZE (b) = 20; BLOCK_INPUT; @@ -568,12 +570,18 @@ CLONE nil means the indirect buffer's state is reset to default values. */) b = allocate_buffer (); + /* No double indirection - if base buffer is indirect, + new buffer becomes an indirect to base's base. */ b->base_buffer = (XBUFFER (base_buffer)->base_buffer ? XBUFFER (base_buffer)->base_buffer : XBUFFER (base_buffer)); /* Use the base buffer's text object. */ b->text = b->base_buffer->text; + /* We have no own text. */ + b->indirections = -1; + /* Notify base buffer that we share the text now. */ + b->base_buffer->indirections++; b->pt = b->base_buffer->pt; b->begv = b->base_buffer->begv; @@ -1439,6 +1447,15 @@ No argument or nil as argument means do this for the current buffer. */) int compact_buffer (struct buffer *buffer) { + /* Verify indirection counters. */ + if (buffer->base_buffer) + { + eassert (buffer->indirections == -1); + eassert (buffer->base_buffer->indirections > 0); + } + else + eassert (buffer->indirections >= 0); + /* Skip dead buffers, indirect buffers and buffers which aren't changed since last compaction. */ if (!NILP (buffer->BUFFER_INTERNAL_FIELD (name)) @@ -1555,10 +1572,19 @@ cleaning up all windows currently displaying the buffer to be killed. */) if (EQ (buffer, XWINDOW (minibuf_window)->buffer)) return Qnil; - /* When we kill a base buffer, kill all its indirect buffers. + /* Notify our base buffer that we don't share the text anymore. */ + if (b->base_buffer) + { + eassert (b->indirections == -1); + b->base_buffer->indirections--; + eassert (b->base_buffer->indirections >= 0); + } + + /* When we kill an ordinary buffer which shares it's buffer text + with indirect buffer(s), we must kill indirect buffer(s) too. We do it at this stage so nothing terrible happens if they ask questions or their hooks get errors. */ - if (! b->base_buffer) + if (!b->base_buffer && b->indirections > 0) { struct buffer *other; diff --git a/src/buffer.h b/src/buffer.h index a97cc13705b..69be4dc7773 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -775,6 +775,11 @@ struct buffer In an ordinary buffer, it is 0. */ struct buffer *base_buffer; + /* In an indirect buffer, this is -1. In an ordinary buffer, + it's the number of indirect buffers which shares our text; + zero means that we're the only owner of this text. */ + int indirections; + /* A non-zero value in slot IDX means that per-buffer variable with index IDX has a local value in this buffer. The index IDX for a buffer-local variable is stored in that variable's slot