emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r105807: Fix bug #9470 with slow redi


From: Eli Zaretskii
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r105807: Fix bug #9470 with slow redisplay in huge single-paragraph buffers.
Date: Sat, 17 Sep 2011 18:18:56 +0300
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 105807
fixes bug(s): http://debbugs.gnu.org/9470
committer: Eli Zaretskii <address@hidden>
branch nick: trunk
timestamp: Sat 2011-09-17 18:18:56 +0300
message:
  Fix bug #9470 with slow redisplay in huge single-paragraph buffers.
  
   src/bidi.c (MAX_PARAGRAPH_SEARCH): New macro.
   (bidi_find_paragraph_start): Search back for paragraph beginning
   at most MAX_PARAGRAPH_SEARCH lines; if not found, return BEGV_BYTE.
   (bidi_move_to_visually_next): Only trigger paragraph-related
   computations when the last character is a newline or at EOB, not
   just any NEUTRAL_B.
   src/xdisp.c (reseat_at_next_visible_line_start): Keep information
   about the current paragraph and restore it after the call to
   reseat.
modified:
  src/ChangeLog
  src/bidi.c
  src/xdisp.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2011-09-17 12:19:04 +0000
+++ b/src/ChangeLog     2011-09-17 15:18:56 +0000
@@ -1,5 +1,16 @@
 2011-09-17  Eli Zaretskii  <address@hidden>
 
+       * xdisp.c (reseat_at_next_visible_line_start): Keep information
+       about the current paragraph and restore it after the call to
+       reseat.
+
+       * bidi.c (MAX_PARAGRAPH_SEARCH): New macro.
+       (bidi_find_paragraph_start): Search back for paragraph beginning
+       at most MAX_PARAGRAPH_SEARCH lines; if not found, return BEGV_BYTE.
+       (bidi_move_to_visually_next): Only trigger paragraph-related
+       computations when the last character is a newline or at EOB, not
+       just any NEUTRAL_B.  (Bug#9470)
+
        * xdisp.c (set_cursor_from_row): Don't invoke special treatment of
        truncated lines if point is covered by a display string.  (Bug#9524)
 

=== modified file 'src/bidi.c'
--- a/src/bidi.c        2011-08-27 12:18:27 +0000
+++ b/src/bidi.c        2011-09-17 15:18:56 +0000
@@ -1071,15 +1071,25 @@
   return val;
 }
 
+/* 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
+   bidi_paragraph_init to about 10 ms.  */
+#define MAX_PARAGRAPH_SEARCH 7500
+
 /* Find the beginning of this paragraph by looking back in the buffer.
-   Value is the byte position of the paragraph's beginning.  */
+   Value is the byte position of the paragraph's beginning, or
+   BEGV_BYTE if paragraph_start_re is still not found after looking
+   back MAX_PARAGRAPH_SEARCH lines in the buffer.  */
 static EMACS_INT
 bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
 {
   Lisp_Object re = paragraph_start_re;
   EMACS_INT limit = ZV, limit_byte = ZV_BYTE;
+  EMACS_INT n = 0;
 
   while (pos_byte > BEGV_BYTE
+        && n++ < MAX_PARAGRAPH_SEARCH
         && fast_looking_at (re, pos, pos_byte, limit, limit_byte, Qnil) < 0)
     {
       /* FIXME: What if the paragraph beginning is covered by a
@@ -1089,6 +1099,8 @@
       pos = find_next_newline_no_quit (pos - 1, -1);
       pos_byte = CHAR_TO_BYTE (pos);
     }
+  if (n >= MAX_PARAGRAPH_SEARCH)
+    pos_byte = BEGV_BYTE;
   return pos_byte;
 }
 
@@ -2239,7 +2251,8 @@
     GCPRO1 (bidi_it->string.lstring);
 
   /* If we just passed a newline, initialize for the next line.  */
-  if (!bidi_it->first_elt && bidi_it->orig_type == NEUTRAL_B)
+  if (!bidi_it->first_elt
+      && (bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB))
     bidi_line_init (bidi_it);
 
   /* Prepare the sentinel iterator state, and cache it.  When we bump
@@ -2320,7 +2333,8 @@
      reordering, whereas we _must_ know the paragraph base direction
      _before_ we process the paragraph's text, since the base
      direction affects the reordering.  */
-  if (bidi_it->scan_dir == 1 && bidi_it->orig_type == NEUTRAL_B)
+  if (bidi_it->scan_dir == 1
+      && (bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB))
     {
       /* The paragraph direction of the entire string, once
         determined, is in effect for the entire string.  Setting the

=== modified file 'src/xdisp.c'
--- a/src/xdisp.c       2011-09-17 08:09:45 +0000
+++ b/src/xdisp.c       2011-09-17 15:18:56 +0000
@@ -5722,6 +5722,9 @@
 {
   int newline_found_p, skipped_p = 0;
   struct bidi_it bidi_it_prev;
+  int new_paragraph, first_elt, disp_prop;
+  EMACS_INT paragraph_end, disp_pos;
+  bidi_dir_t paragraph_dir;
 
   newline_found_p = forward_to_next_line_start (it, &skipped_p, &bidi_it_prev);
 
@@ -5738,6 +5741,23 @@
          forward_to_next_line_start (it, &skipped_p, &bidi_it_prev);
       }
 
+  /* Under bidi iteration, save the attributes of the paragraph we are
+     in, to be restored after the call to `reseat' below.  That's
+     because `reseat' overwrites them, which requires unneeded and
+     potentially expensive backward search for paragraph beginning.
+     This search is unnecessary because we will be `reseat'ed to the
+     same position where we are now, for which we already have all the
+     information we need in the bidi iterator.  */
+  if (it->bidi_p && !STRINGP (it->string))
+    {
+      new_paragraph = it->bidi_it.new_paragraph;
+      first_elt = it->bidi_it.first_elt;
+      paragraph_end = it->bidi_it.separator_limit;
+      paragraph_dir = it->bidi_it.paragraph_dir;
+      disp_pos = it->bidi_it.disp_pos;
+      disp_prop = it->bidi_it.disp_prop;
+    }
+
   /* Position on the newline if that's what's requested.  */
   if (on_newline_p && newline_found_p)
     {
@@ -5777,10 +5797,30 @@
              IT_BYTEPOS (*it) = it->bidi_it.bytepos;
            }
          reseat (it, it->current.pos, 0);
+         if (it->bidi_p)
+           {
+             it->bidi_it.new_paragraph = new_paragraph;
+             it->bidi_it.first_elt = first_elt;
+             it->bidi_it.separator_limit = paragraph_end;
+             it->bidi_it.paragraph_dir = paragraph_dir;
+             it->bidi_it.disp_pos = disp_pos;
+             it->bidi_it.disp_prop = disp_prop;
+           }
        }
     }
   else if (skipped_p)
-    reseat (it, it->current.pos, 0);
+    {
+      reseat (it, it->current.pos, 0);
+      if (it->bidi_p)
+       {
+         it->bidi_it.new_paragraph = new_paragraph;
+         it->bidi_it.first_elt = first_elt;
+         it->bidi_it.separator_limit = paragraph_end;
+         it->bidi_it.paragraph_dir = paragraph_dir;
+         it->bidi_it.disp_pos = disp_pos;
+         it->bidi_it.disp_prop = disp_prop;
+       }
+    }
 
   CHECK_IT (it);
 }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]