aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2014-03-16 18:28:34 +0200
committerEli Zaretskii2014-03-16 18:28:34 +0200
commit2a3d9a06c9a1e6fd4d45eb7c89fd867ca641c563 (patch)
treeb2308944c089627351224b3eca3834971501b716 /src
parentb92631bf71bb029af7a5b4bcf3acd6b4484a4afa (diff)
downloademacs-2a3d9a06c9a1e6fd4d45eb7c89fd867ca641c563.tar.gz
emacs-2a3d9a06c9a1e6fd4d45eb7c89fd867ca641c563.zip
Fix bug #16830 with slow search for newlines in forward-line.
src/search.c (find_newline): Speed up the function when using the newline cache, by halving the number of calls to region_cache_forward and region_cache_backward.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog6
-rw-r--r--src/search.c108
2 files changed, 98 insertions, 16 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 424416398e8..30692059f03 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
12014-03-16 Eli Zaretskii <eliz@gnu.org>
2
3 * search.c (find_newline): Speed up the function when using the
4 newline cache, by halving the number of call to
5 region_cache_forward and region_cache_backward. (Bug#16830)
6
12014-03-15 Juanma Barranquero <lekktu@gmail.com> 72014-03-15 Juanma Barranquero <lekktu@gmail.com>
2 8
3 * buffer.c (Fset_buffer): Document return value (bug#17015). 9 * buffer.c (Fset_buffer): Document return value (bug#17015).
diff --git a/src/search.c b/src/search.c
index 40ab5db495a..3de194c5056 100644
--- a/src/search.c
+++ b/src/search.c
@@ -715,19 +715,62 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
715 examine. */ 715 examine. */
716 ptrdiff_t tem, ceiling_byte = end_byte - 1; 716 ptrdiff_t tem, ceiling_byte = end_byte - 1;
717 717
718 /* If we're looking for a newline, consult the newline cache 718 /* If we're using the newline cache, consult it to see whether
719 to see where we can avoid some scanning. */ 719 we can avoid some scanning. */
720 if (newline_cache) 720 if (newline_cache)
721 { 721 {
722 ptrdiff_t next_change; 722 ptrdiff_t next_change;
723 int result = 1;
724
723 immediate_quit = 0; 725 immediate_quit = 0;
724 while (region_cache_forward 726 while (start < end && result)
725 (cache_buffer, newline_cache, start, &next_change)) 727 {
726 start = next_change; 728 ptrdiff_t lim1;
729
730 result = region_cache_forward (cache_buffer, newline_cache,
731 start, &next_change);
732 if (result)
733 {
734 start = next_change;
735 lim1 = next_change = end;
736 }
737 else
738 lim1 = min (next_change, end);
739
740 /* The cache returned zero for this region; see if
741 this is because the region is known and includes
742 only newlines. While at that, count any newlines
743 we bump into, and exit if we found enough off them. */
744 start_byte = CHAR_TO_BYTE (start);
745 while (start < lim1
746 && FETCH_BYTE (start_byte) == '\n')
747 {
748 start_byte++;
749 start++;
750 if (--count == 0)
751 {
752 if (bytepos)
753 *bytepos = start_byte;
754 return start;
755 }
756 }
757 /* If we found a non-newline character before hitting
758 position where the cache will again return non-zero
759 (i.e. no newlines beyond that position), it means
760 this region is not yet known to the cache, and we
761 must resort to the "dumb loop" method. */
762 if (start < next_change && !result)
763 break;
764 result = 1;
765 }
766 if (start >= end)
767 {
768 start = end;
769 start_byte = end_byte;
770 break;
771 }
727 immediate_quit = allow_quit; 772 immediate_quit = allow_quit;
728 773
729 start_byte = CHAR_TO_BYTE (start);
730
731 /* START should never be after END. */ 774 /* START should never be after END. */
732 if (start_byte > ceiling_byte) 775 if (start_byte > ceiling_byte)
733 start_byte = ceiling_byte; 776 start_byte = ceiling_byte;
@@ -762,9 +805,9 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
762 unsigned char *nl = memchr (lim_addr + cursor, '\n', - cursor); 805 unsigned char *nl = memchr (lim_addr + cursor, '\n', - cursor);
763 next = nl ? nl - lim_addr : 0; 806 next = nl ? nl - lim_addr : 0;
764 807
765 /* If we're looking for newlines, cache the fact that 808 /* If we're using the newline cache, cache the fact that
766 this line's region is free of them. */ 809 the region we just traversed is free of newlines. */
767 if (newline_cache) 810 if (newline_cache && cursor != next)
768 { 811 {
769 know_region_cache (cache_buffer, newline_cache, 812 know_region_cache (cache_buffer, newline_cache,
770 BYTE_TO_CHAR (lim_byte + cursor), 813 BYTE_TO_CHAR (lim_byte + cursor),
@@ -800,14 +843,47 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
800 if (newline_cache) 843 if (newline_cache)
801 { 844 {
802 ptrdiff_t next_change; 845 ptrdiff_t next_change;
846 int result = 1;
847
803 immediate_quit = 0; 848 immediate_quit = 0;
804 while (region_cache_backward 849 while (start > end && result)
805 (cache_buffer, newline_cache, start, &next_change)) 850 {
806 start = next_change; 851 ptrdiff_t lim1;
852
853 result = region_cache_backward (cache_buffer, newline_cache,
854 start, &next_change);
855 if (result)
856 {
857 start = next_change;
858 lim1 = next_change = end;
859 }
860 else
861 lim1 = max (next_change, end);
862 start_byte = CHAR_TO_BYTE (start);
863 while (start > lim1
864 && FETCH_BYTE (start_byte - 1) == '\n')
865 {
866 if (++count == 0)
867 {
868 if (bytepos)
869 *bytepos = start_byte;
870 return start;
871 }
872 start_byte--;
873 start--;
874 }
875 if (start > next_change && !result)
876 break;
877 result = 1;
878 }
879 if (start <= end)
880 {
881 start = end;
882 start_byte = end_byte;
883 break;
884 }
807 immediate_quit = allow_quit; 885 immediate_quit = allow_quit;
808 886
809 start_byte = CHAR_TO_BYTE (start);
810
811 /* Start should never be at or before end. */ 887 /* Start should never be at or before end. */
812 if (start_byte <= ceiling_byte) 888 if (start_byte <= ceiling_byte)
813 start_byte = ceiling_byte + 1; 889 start_byte = ceiling_byte + 1;
@@ -840,7 +916,7 @@ find_newline (ptrdiff_t start, ptrdiff_t start_byte, ptrdiff_t end,
840 916
841 /* If we're looking for newlines, cache the fact that 917 /* If we're looking for newlines, cache the fact that
842 this line's region is free of them. */ 918 this line's region is free of them. */
843 if (newline_cache) 919 if (newline_cache && cursor != prev + 1)
844 { 920 {
845 know_region_cache (cache_buffer, newline_cache, 921 know_region_cache (cache_buffer, newline_cache,
846 BYTE_TO_CHAR (ceiling_byte + prev + 1), 922 BYTE_TO_CHAR (ceiling_byte + prev + 1),