aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Antipov2013-08-06 10:53:09 +0400
committerDmitry Antipov2013-08-06 10:53:09 +0400
commite30b79c1c52a4428189ca148c73e7ecc993c6f6a (patch)
treea7f60977d16877bbe0f626429243ea19543ed84e /src
parent00012b86257f33dd4e08e79b814f4a7ad6010713 (diff)
downloademacs-e30b79c1c52a4428189ca148c73e7ecc993c6f6a.tar.gz
emacs-e30b79c1c52a4428189ca148c73e7ecc993c6f6a.zip
Use region cache to speedup bidi_find_paragraph_start.
* 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'.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog19
-rw-r--r--src/bidi.c39
-rw-r--r--src/buffer.c30
-rw-r--r--src/buffer.h11
-rw-r--r--src/indent.c6
-rw-r--r--src/insdel.c4
-rw-r--r--src/search.c4
7 files changed, 93 insertions, 20 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 7b7d9b56cb5..e8c09b3b4f3 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,24 @@
12013-08-06 Dmitry Antipov <dmantipov@yandex.ru> 12013-08-06 Dmitry Antipov <dmantipov@yandex.ru>
2 2
3 Use region cache to speedup bidi_find_paragraph_start.
4 * buffer.h (struct buffer): New member bidi_paragraph_cache.
5 Rename cache_long_line_scans to cache_long_scans.
6 * buffer.c (bset_cache_long_line_scans): Rename to
7 bset_cache_long_scans.
8 (Fget_buffer_create, Fmake_indirect_buffer, Fkill_buffer)
9 (Fbuffer_swap_text, init_buffer_once): Take bidi_paragraph_cache
10 into account.
11 (syms_of_buffer): Rename cache-long-line-scans to
12 cache-long-scans. Adjust docstring.
13 * search.c (newline_cache_on_off):
14 * indent.c (width_run_cache_on_off): Adjust users.
15 * bidi.c (bidi_paragraph_cache_on_off): New function.
16 (bidi_find_paragraph_start): Use bidi_paragraph_cache if needed.
17 * insdel.c (prepare_to_modify_buffer): Invalidate
18 bidi_paragraph_cache if enabled.
19
202013-08-06 Dmitry Antipov <dmantipov@yandex.ru>
21
3 Invalidate region caches only if buffer text is going to be changed. 22 Invalidate region caches only if buffer text is going to be changed.
4 * lisp.h (modify_region_1): Remove 3rd arg and rename to... 23 * lisp.h (modify_region_1): Remove 3rd arg and rename to...
5 (modify_text): ...new prototype. 24 (modify_text): ...new prototype.
diff --git a/src/bidi.c b/src/bidi.c
index c31d208ecbc..7d082a94997 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -61,6 +61,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
61#include "character.h" 61#include "character.h"
62#include "buffer.h" 62#include "buffer.h"
63#include "dispextern.h" 63#include "dispextern.h"
64#include "region-cache.h"
64 65
65static bool bidi_initialized = 0; 66static bool bidi_initialized = 0;
66 67
@@ -1085,6 +1086,29 @@ bidi_at_paragraph_end (ptrdiff_t charpos, ptrdiff_t bytepos)
1085 return val; 1086 return val;
1086} 1087}
1087 1088
1089/* If the user has requested the long scans caching, make sure that
1090 BIDI cache is enabled. Otherwise, make sure it's disabled. */
1091
1092static struct region_cache *
1093bidi_paragraph_cache_on_off (void)
1094{
1095 if (NILP (BVAR (current_buffer, cache_long_scans)))
1096 {
1097 if (current_buffer->bidi_paragraph_cache)
1098 {
1099 free_region_cache (current_buffer->bidi_paragraph_cache);
1100 current_buffer->bidi_paragraph_cache = 0;
1101 }
1102 return NULL;
1103 }
1104 else
1105 {
1106 if (!current_buffer->bidi_paragraph_cache)
1107 current_buffer->bidi_paragraph_cache = new_region_cache ();
1108 return current_buffer->bidi_paragraph_cache;
1109 }
1110}
1111
1088/* On my 2005-vintage machine, searching back for paragraph start 1112/* On my 2005-vintage machine, searching back for paragraph start
1089 takes ~1 ms per line. And bidi_paragraph_init is called 4 times 1113 takes ~1 ms per line. And bidi_paragraph_init is called 4 times
1090 when user types C-p. The number below limits each call to 1114 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)
1100{ 1124{
1101 Lisp_Object re = paragraph_start_re; 1125 Lisp_Object re = paragraph_start_re;
1102 ptrdiff_t limit = ZV, limit_byte = ZV_BYTE; 1126 ptrdiff_t limit = ZV, limit_byte = ZV_BYTE;
1103 ptrdiff_t n = 0; 1127 struct region_cache *bpc = bidi_paragraph_cache_on_off ();
1128 ptrdiff_t n = 0, oldpos = pos, next;
1104 1129
1105 while (pos_byte > BEGV_BYTE 1130 while (pos_byte > BEGV_BYTE
1106 && n++ < MAX_PARAGRAPH_SEARCH 1131 && n++ < MAX_PARAGRAPH_SEARCH
@@ -1111,10 +1136,18 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
1111 of the text over which we scan back includes 1136 of the text over which we scan back includes
1112 paragraph_start_re? */ 1137 paragraph_start_re? */
1113 DEC_BOTH (pos, pos_byte); 1138 DEC_BOTH (pos, pos_byte);
1114 pos = find_newline_no_quit (pos, pos_byte, -1, &pos_byte); 1139 if (bpc && region_cache_backward (current_buffer, bpc, pos, &next))
1140 {
1141 pos = next, pos_byte = CHAR_TO_BYTE (pos);
1142 break;
1143 }
1144 else
1145 pos = find_newline_no_quit (pos, pos_byte, -1, &pos_byte);
1115 } 1146 }
1116 if (n >= MAX_PARAGRAPH_SEARCH) 1147 if (n >= MAX_PARAGRAPH_SEARCH)
1117 pos_byte = BEGV_BYTE; 1148 pos = BEGV, pos_byte = BEGV_BYTE;
1149 if (bpc)
1150 know_region_cache (current_buffer, bpc, pos, oldpos);
1118 return pos_byte; 1151 return pos_byte;
1119} 1152}
1120 1153
diff --git a/src/buffer.c b/src/buffer.c
index f9154d42b03..339175d9078 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -203,9 +203,9 @@ bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val)
203 b->INTERNAL_FIELD (buffer_file_coding_system) = val; 203 b->INTERNAL_FIELD (buffer_file_coding_system) = val;
204} 204}
205static void 205static void
206bset_cache_long_line_scans (struct buffer *b, Lisp_Object val) 206bset_cache_long_scans (struct buffer *b, Lisp_Object val)
207{ 207{
208 b->INTERNAL_FIELD (cache_long_line_scans) = val; 208 b->INTERNAL_FIELD (cache_long_scans) = val;
209} 209}
210static void 210static void
211bset_case_fold_search (struct buffer *b, Lisp_Object val) 211bset_case_fold_search (struct buffer *b, Lisp_Object val)
@@ -583,6 +583,7 @@ even if it is dead. The return value is never nil. */)
583 583
584 b->newline_cache = 0; 584 b->newline_cache = 0;
585 b->width_run_cache = 0; 585 b->width_run_cache = 0;
586 b->bidi_paragraph_cache = 0;
586 bset_width_table (b, Qnil); 587 bset_width_table (b, Qnil);
587 b->prevent_redisplay_optimizations_p = 1; 588 b->prevent_redisplay_optimizations_p = 1;
588 589
@@ -806,6 +807,7 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
806 807
807 b->newline_cache = 0; 808 b->newline_cache = 0;
808 b->width_run_cache = 0; 809 b->width_run_cache = 0;
810 b->bidi_paragraph_cache = 0;
809 bset_width_table (b, Qnil); 811 bset_width_table (b, Qnil);
810 812
811 name = Fcopy_sequence (name); 813 name = Fcopy_sequence (name);
@@ -1945,6 +1947,11 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1945 free_region_cache (b->width_run_cache); 1947 free_region_cache (b->width_run_cache);
1946 b->width_run_cache = 0; 1948 b->width_run_cache = 0;
1947 } 1949 }
1950 if (b->bidi_paragraph_cache)
1951 {
1952 free_region_cache (b->bidi_paragraph_cache);
1953 b->bidi_paragraph_cache = 0;
1954 }
1948 bset_width_table (b, Qnil); 1955 bset_width_table (b, Qnil);
1949 unblock_input (); 1956 unblock_input ();
1950 bset_undo_list (b, Qnil); 1957 bset_undo_list (b, Qnil);
@@ -2355,6 +2362,7 @@ DEFUN ("buffer-swap-text", Fbuffer_swap_text, Sbuffer_swap_text,
2355 current_buffer->clip_changed = 1; other_buffer->clip_changed = 1; 2362 current_buffer->clip_changed = 1; other_buffer->clip_changed = 1;
2356 swapfield (newline_cache, struct region_cache *); 2363 swapfield (newline_cache, struct region_cache *);
2357 swapfield (width_run_cache, struct region_cache *); 2364 swapfield (width_run_cache, struct region_cache *);
2365 swapfield (bidi_paragraph_cache, struct region_cache *);
2358 current_buffer->prevent_redisplay_optimizations_p = 1; 2366 current_buffer->prevent_redisplay_optimizations_p = 1;
2359 other_buffer->prevent_redisplay_optimizations_p = 1; 2367 other_buffer->prevent_redisplay_optimizations_p = 1;
2360 swapfield (overlays_before, struct Lisp_Overlay *); 2368 swapfield (overlays_before, struct Lisp_Overlay *);
@@ -5169,7 +5177,7 @@ init_buffer_once (void)
5169 bset_buffer_file_coding_system (&buffer_defaults, Qnil); 5177 bset_buffer_file_coding_system (&buffer_defaults, Qnil);
5170 XSETFASTINT (BVAR (&buffer_defaults, fill_column), 70); 5178 XSETFASTINT (BVAR (&buffer_defaults, fill_column), 70);
5171 XSETFASTINT (BVAR (&buffer_defaults, left_margin), 0); 5179 XSETFASTINT (BVAR (&buffer_defaults, left_margin), 0);
5172 bset_cache_long_line_scans (&buffer_defaults, Qnil); 5180 bset_cache_long_scans (&buffer_defaults, Qnil);
5173 bset_file_truename (&buffer_defaults, Qnil); 5181 bset_file_truename (&buffer_defaults, Qnil);
5174 XSETFASTINT (BVAR (&buffer_defaults, display_count), 0); 5182 XSETFASTINT (BVAR (&buffer_defaults, display_count), 0);
5175 XSETFASTINT (BVAR (&buffer_defaults, left_margin_cols), 0); 5183 XSETFASTINT (BVAR (&buffer_defaults, left_margin_cols), 0);
@@ -5233,7 +5241,7 @@ init_buffer_once (void)
5233 XSETFASTINT (BVAR (&buffer_local_flags, abbrev_table), idx); ++idx; 5241 XSETFASTINT (BVAR (&buffer_local_flags, abbrev_table), idx); ++idx;
5234 XSETFASTINT (BVAR (&buffer_local_flags, display_table), idx); ++idx; 5242 XSETFASTINT (BVAR (&buffer_local_flags, display_table), idx); ++idx;
5235 XSETFASTINT (BVAR (&buffer_local_flags, syntax_table), idx); ++idx; 5243 XSETFASTINT (BVAR (&buffer_local_flags, syntax_table), idx); ++idx;
5236 XSETFASTINT (BVAR (&buffer_local_flags, cache_long_line_scans), idx); ++idx; 5244 XSETFASTINT (BVAR (&buffer_local_flags, cache_long_scans), idx); ++idx;
5237 XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx; 5245 XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx;
5238 XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx; 5246 XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx;
5239 XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_direction), idx); ++idx; 5247 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. */);
6120 DEFVAR_PER_BUFFER ("mark-active", &BVAR (current_buffer, mark_active), Qnil, 6128 DEFVAR_PER_BUFFER ("mark-active", &BVAR (current_buffer, mark_active), Qnil,
6121 doc: /* Non-nil means the mark and region are currently active in this buffer. */); 6129 doc: /* Non-nil means the mark and region are currently active in this buffer. */);
6122 6130
6123 DEFVAR_PER_BUFFER ("cache-long-line-scans", &BVAR (current_buffer, cache_long_line_scans), Qnil, 6131 DEFVAR_PER_BUFFER ("cache-long-scans", &BVAR (current_buffer, cache_long_scans), Qnil,
6124 doc: /* Non-nil means that Emacs should use caches to handle long lines more quickly. 6132 doc: /* Non-nil means that Emacs should use caches in attempt to speedup buffer scans.
6125 6133
6126Normally, the line-motion functions work by scanning the buffer for 6134Normally, the line-motion functions work by scanning the buffer for
6127newlines. Columnar operations (like `move-to-column' and 6135newlines. Columnar operations (like `move-to-column' and
@@ -6131,18 +6139,24 @@ buffer's lines are very long (say, more than 500 characters), these
6131motion functions will take longer to execute. Emacs may also take 6139motion functions will take longer to execute. Emacs may also take
6132longer to update the display. 6140longer to update the display.
6133 6141
6134If `cache-long-line-scans' is non-nil, these motion functions cache the 6142If `cache-long-scans' is non-nil, these motion functions cache the
6135results of their scans, and consult the cache to avoid rescanning 6143results of their scans, and consult the cache to avoid rescanning
6136regions of the buffer until the text is modified. The caches are most 6144regions of the buffer until the text is modified. The caches are most
6137beneficial when they prevent the most searching---that is, when the 6145beneficial when they prevent the most searching---that is, when the
6138buffer contains long lines and large regions of characters with the 6146buffer contains long lines and large regions of characters with the
6139same, fixed screen width. 6147same, fixed screen width.
6140 6148
6141When `cache-long-line-scans' is non-nil, processing short lines will 6149When `cache-long-scans' is non-nil, processing short lines will
6142become slightly slower (because of the overhead of consulting the 6150become slightly slower (because of the overhead of consulting the
6143cache), and the caches will use memory roughly proportional to the 6151cache), and the caches will use memory roughly proportional to the
6144number of newlines and characters whose screen width varies. 6152number of newlines and characters whose screen width varies.
6145 6153
6154Bidirectional editing also requires buffer scans to find paragraph
6155separators. If you have large paragraphs or no paragraph separators
6156at all, these scans may be slow. If `cache-long-scans' is non-nil,
6157results of these scans are cached. This doesn't help too much if
6158paragraphs are of the reasonable (few thousands of characters) size.
6159
6146The caches require no explicit maintenance; their accuracy is 6160The caches require no explicit maintenance; their accuracy is
6147maintained internally by the Emacs primitives. Enabling or disabling 6161maintained internally by the Emacs primitives. Enabling or disabling
6148the cache should not affect the behavior of any of the motion 6162the cache should not affect the behavior of any of the motion
diff --git a/src/buffer.h b/src/buffer.h
index 646f8f72232..221db39329a 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -632,9 +632,9 @@ struct buffer
632 /* List of symbols naming the file format used for auto-save file. */ 632 /* List of symbols naming the file format used for auto-save file. */
633 Lisp_Object INTERNAL_FIELD (auto_save_file_format); 633 Lisp_Object INTERNAL_FIELD (auto_save_file_format);
634 634
635 /* True if the newline position cache and width run cache are 635 /* True if the newline position cache, width run cache and BIDI paragraph
636 enabled. See search.c and indent.c. */ 636 cache are enabled. See search.c, indent.c and bidi.c for details. */
637 Lisp_Object INTERNAL_FIELD (cache_long_line_scans); 637 Lisp_Object INTERNAL_FIELD (cache_long_scans);
638 638
639 /* If the width run cache is enabled, this table contains the 639 /* If the width run cache is enabled, this table contains the
640 character widths width_run_cache (see above) assumes. When we 640 character widths width_run_cache (see above) assumes. When we
@@ -839,9 +839,12 @@ struct buffer
839 the character's width; if it maps a character to zero, we don't 839 the character's width; if it maps a character to zero, we don't
840 know what its width is. This allows compute_motion to process 840 know what its width is. This allows compute_motion to process
841 such regions very quickly, using algebra instead of inspecting 841 such regions very quickly, using algebra instead of inspecting
842 each character. See also width_table, below. */ 842 each character. See also width_table, below.
843
844 The latter cache is used to speedup bidi_find_paragraph_start. */
843 struct region_cache *newline_cache; 845 struct region_cache *newline_cache;
844 struct region_cache *width_run_cache; 846 struct region_cache *width_run_cache;
847 struct region_cache *bidi_paragraph_cache;
845 848
846 /* Non-zero means don't use redisplay optimizations for 849 /* Non-zero means don't use redisplay optimizations for
847 displaying this buffer. */ 850 displaying this buffer. */
diff --git a/src/indent.c b/src/indent.c
index 47358e17db8..6aaf86579d7 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -141,13 +141,13 @@ recompute_width_table (struct buffer *buf, struct Lisp_Char_Table *disptab)
141 XSETFASTINT (widthtab->contents[i], character_width (i, disptab)); 141 XSETFASTINT (widthtab->contents[i], character_width (i, disptab));
142} 142}
143 143
144/* Allocate or free the width run cache, as requested by the current 144/* Allocate or free the width run cache, as requested by the
145 state of current_buffer's cache_long_line_scans variable. */ 145 current state of current_buffer's cache_long_scans variable. */
146 146
147static void 147static void
148width_run_cache_on_off (void) 148width_run_cache_on_off (void)
149{ 149{
150 if (NILP (BVAR (current_buffer, cache_long_line_scans)) 150 if (NILP (BVAR (current_buffer, cache_long_scans))
151 /* And, for the moment, this feature doesn't work on multibyte 151 /* And, for the moment, this feature doesn't work on multibyte
152 characters. */ 152 characters. */
153 || !NILP (BVAR (current_buffer, enable_multibyte_characters))) 153 || !NILP (BVAR (current_buffer, enable_multibyte_characters)))
diff --git a/src/insdel.c b/src/insdel.c
index ac64299a997..f746fd34330 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -1879,6 +1879,10 @@ prepare_to_modify_buffer (ptrdiff_t start, ptrdiff_t end,
1879 invalidate_region_cache (current_buffer, 1879 invalidate_region_cache (current_buffer,
1880 current_buffer->width_run_cache, 1880 current_buffer->width_run_cache,
1881 start - BEG, Z - end); 1881 start - BEG, Z - end);
1882 if (current_buffer->bidi_paragraph_cache)
1883 invalidate_region_cache (current_buffer,
1884 current_buffer->bidi_paragraph_cache,
1885 start - BEG, Z - end);
1882} 1886}
1883 1887
1884/* These macros work with an argument named `preserve_ptr' 1888/* These macros work with an argument named `preserve_ptr'
diff --git a/src/search.c b/src/search.c
index 0f4d41586a3..761c12a364a 100644
--- a/src/search.c
+++ b/src/search.c
@@ -598,14 +598,14 @@ fast_looking_at (Lisp_Object regexp, ptrdiff_t pos, ptrdiff_t pos_byte,
598 598
599/* The newline cache: remembering which sections of text have no newlines. */ 599/* The newline cache: remembering which sections of text have no newlines. */
600 600
601/* If the user has requested newline caching, make sure it's on. 601/* If the user has requested the long scans caching, make sure it's on.
602 Otherwise, make sure it's off. 602 Otherwise, make sure it's off.
603 This is our cheezy way of associating an action with the change of 603 This is our cheezy way of associating an action with the change of
604 state of a buffer-local variable. */ 604 state of a buffer-local variable. */
605static void 605static void
606newline_cache_on_off (struct buffer *buf) 606newline_cache_on_off (struct buffer *buf)
607{ 607{
608 if (NILP (BVAR (buf, cache_long_line_scans))) 608 if (NILP (BVAR (buf, cache_long_scans)))
609 { 609 {
610 /* It should be off. */ 610 /* It should be off. */
611 if (buf->newline_cache) 611 if (buf->newline_cache)