]> git.eshelyaron.com Git - emacs.git/commitdiff
Use region cache to speedup bidi_find_paragraph_start.
authorDmitry Antipov <dmantipov@yandex.ru>
Tue, 6 Aug 2013 06:53:09 +0000 (10:53 +0400)
committerDmitry Antipov <dmantipov@yandex.ru>
Tue, 6 Aug 2013 06:53:09 +0000 (10:53 +0400)
* src/buffer.h (struct buffer): New member bidi_paragraph_cache.
Rename cache_long_line_scans to cache_long_scans.
* src/buffer.c (bset_cache_long_line_scans): Rename to
bset_cache_long_scans.
(Fget_buffer_create, Fmake_indirect_buffer, Fkill_buffer)
(Fbuffer_swap_text, init_buffer_once): Take bidi_paragraph_cache
into account.
(syms_of_buffer): Rename cache-long-line-scans to
cache-long-scans.  Adjust docstring.
* src/search.c (newline_cache_on_off):
* src/indent.c (width_run_cache_on_off): Adjust users.
* src/bidi.c (bidi_paragraph_cache_on_off): New function.
(bidi_find_paragraph_start): Use bidi_paragraph_cache if needed.
* src/insdel.c (prepare_to_modify_buffer): Invalidate
bidi_paragraph_cache if enabled.
* doc/lispref/positions.texi (Motion by Screen Lines):
* doc/lispref/display.texi (Truncation): Rename `cache-long-line-scans'
to `cache-long-scans'.

doc/lispref/ChangeLog
doc/lispref/display.texi
doc/lispref/positions.texi
src/ChangeLog
src/bidi.c
src/buffer.c
src/buffer.h
src/indent.c
src/insdel.c
src/search.c

index 82bc279fa5bfb17b65ec4ff54112e6821e7e1ce9..0aac5235a29082a39577a290f5e776255b793dfd 100644 (file)
@@ -1,3 +1,9 @@
+2013-08-06  Dmitry Antipov  <dmantipov@yandex.ru>
+
+       * positions.texi (Motion by Screen Lines):
+       * display.texi (Truncation): Rename `cache-long-line-scans'
+       to `cache-long-scans'.
+
 2013-08-05  Xue Fuqiao  <xfq.free@gmail.com>
 
        * windows.texi (Window Start and End): Add an index.
index c5068425c660e7cb8738ece52c93127bc6831b40..59a6f5ce3404cb704828213213b03e8dd48aa7fa 100644 (file)
@@ -217,9 +217,9 @@ over the @code{line-prefix} variable.  @xref{Special Properties}.
 continuation to display them, computing the continuation lines can
 make redisplay slow.  The column computation and indentation functions
 also become slow.  Then you might find it advisable to set
-@code{cache-long-line-scans} to @code{t}.
+@code{cache-long-scans} to @code{t}.
 
-@defvar cache-long-line-scans
+@defvar cache-long-scans
 If this variable is non-@code{nil}, various indentation and motion
 functions, and Emacs redisplay, cache the results of scanning the
 buffer, and consult the cache to avoid rescanning regions of the buffer
index e8b6166f63c088c577a65e38adc256aac6c5b95c..119ad98a53d8572994721a2dcde1c1f18aaebfbf 100644 (file)
@@ -483,7 +483,7 @@ Display}.
   These functions scan text to determine where screen lines break, and
 thus take time proportional to the distance scanned.  If you intend to
 use them heavily, Emacs provides caches which may improve the
-performance of your code.  @xref{Truncation, cache-long-line-scans}.
+performance of your code.  @xref{Truncation, cache-long-scans}.
 
 @defun vertical-motion count &optional window
 This function moves point to the start of the screen line @var{count}
index 7b7d9b56cb5b9b4625ba423d5913c2492d04a3c9..e8c09b3b4f32d58198e745add2b4832a1f63a518 100644 (file)
@@ -1,3 +1,22 @@
+2013-08-06  Dmitry Antipov  <dmantipov@yandex.ru>
+
+       Use region cache to speedup bidi_find_paragraph_start.
+       * buffer.h (struct buffer): New member bidi_paragraph_cache.
+       Rename cache_long_line_scans to cache_long_scans.
+       * buffer.c (bset_cache_long_line_scans): Rename to
+       bset_cache_long_scans.
+       (Fget_buffer_create, Fmake_indirect_buffer, Fkill_buffer)
+       (Fbuffer_swap_text, init_buffer_once): Take bidi_paragraph_cache
+       into account.
+       (syms_of_buffer): Rename cache-long-line-scans to
+       cache-long-scans.  Adjust docstring.
+       * search.c (newline_cache_on_off):
+       * indent.c (width_run_cache_on_off): Adjust users.
+       * bidi.c (bidi_paragraph_cache_on_off): New function.
+       (bidi_find_paragraph_start): Use bidi_paragraph_cache if needed.
+       * insdel.c (prepare_to_modify_buffer): Invalidate
+       bidi_paragraph_cache if enabled.
+
 2013-08-06  Dmitry Antipov  <dmantipov@yandex.ru>
 
        Invalidate region caches only if buffer text is going to be changed.
index c31d208ecbc8dbf5139ab7915522cc0e1a2b6291..7d082a949979240c8e24cb663a66eee53e896b52 100644 (file)
@@ -61,6 +61,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "character.h"
 #include "buffer.h"
 #include "dispextern.h"
+#include "region-cache.h"
 
 static bool bidi_initialized = 0;
 
@@ -1085,6 +1086,29 @@ bidi_at_paragraph_end (ptrdiff_t charpos, ptrdiff_t bytepos)
   return val;
 }
 
+/* If the user has requested the long scans caching, make sure that
+   BIDI cache is enabled.  Otherwise, make sure it's disabled.  */
+
+static struct region_cache *
+bidi_paragraph_cache_on_off (void)
+{
+  if (NILP (BVAR (current_buffer, cache_long_scans)))
+    {
+      if (current_buffer->bidi_paragraph_cache)
+       {
+         free_region_cache (current_buffer->bidi_paragraph_cache);
+         current_buffer->bidi_paragraph_cache = 0;
+       }
+      return NULL;
+    }
+  else
+    {
+      if (!current_buffer->bidi_paragraph_cache)
+       current_buffer->bidi_paragraph_cache = new_region_cache ();
+      return current_buffer->bidi_paragraph_cache;
+    }
+}
+
 /* On my 2005-vintage machine, searching back for paragraph start
    takes ~1 ms per line.  And bidi_paragraph_init is called 4 times
    when user types C-p.  The number below limits each call to
@@ -1100,7 +1124,8 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
 {
   Lisp_Object re = paragraph_start_re;
   ptrdiff_t limit = ZV, limit_byte = ZV_BYTE;
-  ptrdiff_t n = 0;
+  struct region_cache *bpc = bidi_paragraph_cache_on_off ();
+  ptrdiff_t n = 0, oldpos = pos, next;
 
   while (pos_byte > BEGV_BYTE
         && n++ < MAX_PARAGRAPH_SEARCH
@@ -1111,10 +1136,18 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
         of the text over which we scan back includes
         paragraph_start_re?  */
       DEC_BOTH (pos, pos_byte);
-      pos = find_newline_no_quit (pos, pos_byte, -1, &pos_byte);
+      if (bpc && region_cache_backward (current_buffer, bpc, pos, &next))
+       {
+         pos = next, pos_byte = CHAR_TO_BYTE (pos);
+         break;
+       }
+      else
+       pos = find_newline_no_quit (pos, pos_byte, -1, &pos_byte);
     }
   if (n >= MAX_PARAGRAPH_SEARCH)
-    pos_byte = BEGV_BYTE;
+    pos = BEGV, pos_byte = BEGV_BYTE;
+  if (bpc)
+    know_region_cache (current_buffer, bpc, pos, oldpos);
   return pos_byte;
 }
 
index f9154d42b030bab7f663bc47d16086952212579e..339175d90783bab3bc9ec10aabb890127ae6df2a 100644 (file)
@@ -203,9 +203,9 @@ bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val)
   b->INTERNAL_FIELD (buffer_file_coding_system) = val;
 }
 static void
-bset_cache_long_line_scans (struct buffer *b, Lisp_Object val)
+bset_cache_long_scans (struct buffer *b, Lisp_Object val)
 {
-  b->INTERNAL_FIELD (cache_long_line_scans) = val;
+  b->INTERNAL_FIELD (cache_long_scans) = val;
 }
 static void
 bset_case_fold_search (struct buffer *b, Lisp_Object val)
@@ -583,6 +583,7 @@ even if it is dead.  The return value is never nil.  */)
 
   b->newline_cache = 0;
   b->width_run_cache = 0;
+  b->bidi_paragraph_cache = 0;
   bset_width_table (b, Qnil);
   b->prevent_redisplay_optimizations_p = 1;
 
@@ -806,6 +807,7 @@ CLONE nil means the indirect buffer's state is reset to default values.  */)
 
   b->newline_cache = 0;
   b->width_run_cache = 0;
+  b->bidi_paragraph_cache = 0;
   bset_width_table (b, Qnil);
 
   name = Fcopy_sequence (name);
@@ -1945,6 +1947,11 @@ cleaning up all windows currently displaying the buffer to be killed. */)
       free_region_cache (b->width_run_cache);
       b->width_run_cache = 0;
     }
+  if (b->bidi_paragraph_cache)
+    {
+      free_region_cache (b->bidi_paragraph_cache);
+      b->bidi_paragraph_cache = 0;
+    }
   bset_width_table (b, Qnil);
   unblock_input ();
   bset_undo_list (b, Qnil);
@@ -2355,6 +2362,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
   current_buffer->clip_changed = 1;    other_buffer->clip_changed = 1;
   swapfield (newline_cache, struct region_cache *);
   swapfield (width_run_cache, struct region_cache *);
+  swapfield (bidi_paragraph_cache, struct region_cache *);
   current_buffer->prevent_redisplay_optimizations_p = 1;
   other_buffer->prevent_redisplay_optimizations_p = 1;
   swapfield (overlays_before, struct Lisp_Overlay *);
@@ -5169,7 +5177,7 @@ init_buffer_once (void)
   bset_buffer_file_coding_system (&buffer_defaults, Qnil);
   XSETFASTINT (BVAR (&buffer_defaults, fill_column), 70);
   XSETFASTINT (BVAR (&buffer_defaults, left_margin), 0);
-  bset_cache_long_line_scans (&buffer_defaults, Qnil);
+  bset_cache_long_scans (&buffer_defaults, Qnil);
   bset_file_truename (&buffer_defaults, Qnil);
   XSETFASTINT (BVAR (&buffer_defaults, display_count), 0);
   XSETFASTINT (BVAR (&buffer_defaults, left_margin_cols), 0);
@@ -5233,7 +5241,7 @@ init_buffer_once (void)
   XSETFASTINT (BVAR (&buffer_local_flags, abbrev_table), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, display_table), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, syntax_table), idx); ++idx;
-  XSETFASTINT (BVAR (&buffer_local_flags, cache_long_line_scans), idx); ++idx;
+  XSETFASTINT (BVAR (&buffer_local_flags, cache_long_scans), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx;
   XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_direction), idx); ++idx;
@@ -6120,8 +6128,8 @@ If the value of the variable is t, undo information is not recorded.  */);
   DEFVAR_PER_BUFFER ("mark-active", &BVAR (current_buffer, mark_active), Qnil,
                     doc: /* Non-nil means the mark and region are currently active in this buffer.  */);
 
-  DEFVAR_PER_BUFFER ("cache-long-line-scans", &BVAR (current_buffer, cache_long_line_scans), Qnil,
-                    doc: /* Non-nil means that Emacs should use caches to handle long lines more quickly.
+  DEFVAR_PER_BUFFER ("cache-long-scans", &BVAR (current_buffer, cache_long_scans), Qnil,
+                    doc: /* Non-nil means that Emacs should use caches in attempt to speedup buffer scans.
 
 Normally, the line-motion functions work by scanning the buffer for
 newlines.  Columnar operations (like `move-to-column' and
@@ -6131,18 +6139,24 @@ buffer's lines are very long (say, more than 500 characters), these
 motion functions will take longer to execute.  Emacs may also take
 longer to update the display.
 
-If `cache-long-line-scans' is non-nil, these motion functions cache the
+If `cache-long-scans' is non-nil, these motion functions cache the
 results of their scans, and consult the cache to avoid rescanning
 regions of the buffer until the text is modified.  The caches are most
 beneficial when they prevent the most searching---that is, when the
 buffer contains long lines and large regions of characters with the
 same, fixed screen width.
 
-When `cache-long-line-scans' is non-nil, processing short lines will
+When `cache-long-scans' is non-nil, processing short lines will
 become slightly slower (because of the overhead of consulting the
 cache), and the caches will use memory roughly proportional to the
 number of newlines and characters whose screen width varies.
 
+Bidirectional editing also requires buffer scans to find paragraph
+separators.  If you have large paragraphs or no paragraph separators
+at all, these scans may be slow.  If `cache-long-scans' is non-nil,
+results of these scans are cached.  This doesn't help too much if
+paragraphs are of the reasonable (few thousands of characters) size.
+
 The caches require no explicit maintenance; their accuracy is
 maintained internally by the Emacs primitives.  Enabling or disabling
 the cache should not affect the behavior of any of the motion
index 646f8f72232e9b3848b93d487b33a4b3235df5cd..221db39329aaf4744b45065a268f6b21151ee638 100644 (file)
@@ -632,9 +632,9 @@ struct buffer
   /* List of symbols naming the file format used for auto-save file.  */
   Lisp_Object INTERNAL_FIELD (auto_save_file_format);
 
-  /* True if the newline position cache and width run cache are
-     enabled.  See search.c and indent.c.  */
-  Lisp_Object INTERNAL_FIELD (cache_long_line_scans);
+  /* True if the newline position cache, width run cache and BIDI paragraph
+     cache are enabled.  See search.c, indent.c and bidi.c for details.  */
+  Lisp_Object INTERNAL_FIELD (cache_long_scans);
 
   /* If the width run cache is enabled, this table contains the
      character widths width_run_cache (see above) assumes.  When we
@@ -839,9 +839,12 @@ struct buffer
      the character's width; if it maps a character to zero, we don't
      know what its width is.  This allows compute_motion to process
      such regions very quickly, using algebra instead of inspecting
-     each character.   See also width_table, below.  */
+     each character.   See also width_table, below.
+
+     The latter cache is used to speedup bidi_find_paragraph_start.  */
   struct region_cache *newline_cache;
   struct region_cache *width_run_cache;
+  struct region_cache *bidi_paragraph_cache;
 
   /* Non-zero means don't use redisplay optimizations for
      displaying this buffer.  */
index 47358e17db8174f2c087cbd78c24039ac229db1b..6aaf86579d731aa83853efde881cdbe073d9ce9d 100644 (file)
@@ -141,13 +141,13 @@ recompute_width_table (struct buffer *buf, struct Lisp_Char_Table *disptab)
     XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
 }
 
-/* Allocate or free the width run cache, as requested by the current
-   state of current_buffer's cache_long_line_scans variable.  */
+/* Allocate or free the width run cache, as requested by the
+   current state of current_buffer's cache_long_scans variable.  */
 
 static void
 width_run_cache_on_off (void)
 {
-  if (NILP (BVAR (current_buffer, cache_long_line_scans))
+  if (NILP (BVAR (current_buffer, cache_long_scans))
       /* And, for the moment, this feature doesn't work on multibyte
          characters.  */
       || !NILP (BVAR (current_buffer, enable_multibyte_characters)))
index ac64299a99763393ecac2d08849a134f5932e1ab..f746fd3433012d04ced2c2f24c2b4c61ea23e5d9 100644 (file)
@@ -1879,6 +1879,10 @@ prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end,
     invalidate_region_cache (current_buffer,
                              current_buffer->width_run_cache,
                              start - BEG, Z - end);
+  if (current_buffer->bidi_paragraph_cache)
+    invalidate_region_cache (current_buffer,
+                             current_buffer->bidi_paragraph_cache,
+                             start - BEG, Z - end);
 }
 
 /* These macros work with an argument named `preserve_ptr'
index 0f4d41586a3e36b8e68c58e2359915222d5e0d9f..761c12a364a7b4dd40aab42fb3deae571e000cb7 100644 (file)
@@ -598,14 +598,14 @@ fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte,
 \f
 /* The newline cache: remembering which sections of text have no newlines.  */
 
-/* If the user has requested newline caching, make sure it's on.
+/* If the user has requested the long scans caching, make sure it's on.
    Otherwise, make sure it's off.
    This is our cheezy way of associating an action with the change of
    state of a buffer-local variable.  */
 static void
 newline_cache_on_off (struct buffer *buf)
 {
-  if (NILP (BVAR (buf, cache_long_line_scans)))
+  if (NILP (BVAR (buf, cache_long_scans)))
     {
       /* It should be off.  */
       if (buf->newline_cache)