diff src/line-number.c @ 284:558f606b08ae r21-0b40

Import from CVS: tag r21-0b40
author cvs
date Mon, 13 Aug 2007 10:34:13 +0200
parents f955c73f5258
children 57709be46d1b
line wrap: on
line diff
--- a/src/line-number.c	Mon Aug 13 10:33:19 2007 +0200
+++ b/src/line-number.c	Mon Aug 13 10:34:13 2007 +0200
@@ -22,18 +22,18 @@
 
 /* To calculate the line numbers, redisplay must count the newlines
    from a known position.  This used to be BUF_BEGV, but this made the
-   redisplay extremely slow for large buffers, because Emacs must
-   rescan the whole buffer at each redisplay, just to count the
-   newlines.
+   line numbering extremely slow for large buffers, because Emacs had
+   to rescan the whole buffer at each redisplay.
 
-   To make line numbering efficient, we maintain a simple-minded
-   cache.  Each buffer contains a small ring of known positions, each
-   element of the ring being a Lisp_Object -- either nil or a cons of
-   a buffer position and the line number (beginning with 0).
+   To make line numbering efficient, we maintain a buffer-local cache
+   of recently used positions and their line numbers.  The cache is
+   implemented as a small ring of cache positions.  A cache position
+   is either nil or a cons of a buffer position (marker) and the
+   corresponding line number.
 
    When calculating the line numbers, this cache is consulted if it
    would otherwise take too much time to count the newlines in the
-   buffer (see the comment to window_line_number.)
+   buffer (see the comment to buffer_line_number().)
 
    Insertion and deletions that contain/delete newlines invalidate the
    cached positions after the insertion point.  This guarantees
@@ -42,7 +42,7 @@
    the buffers where the cache is actually initialized -- i.e. where
    line-numbering is on, and you move the point farther than
    LINE_NUMBER_FAR from the beginning of buffer.  In this sense, the
-   cache is lazy.  If you don't use it, you don't pay for it.
+   cache is lazy -- if you don't use it, you don't pay for it.
 
    NOTE: line-number cache should not be confused with line-start
    cache.  Line-start cache (a part of redisplay) works with the
@@ -56,21 +56,18 @@
 
 #include "line-number.h"
 
-
-/* #### The following three values could use some tweaking, to get the
-   best performance.  I suspect LINE_NUMBER_FAR and
-   LINE_NUMBER_LARGE_STRING could be made bigger.  */
+/* #### The following three values could stand more exploration for
+   best performance.  */
 
 /* Size of the ring.  The current code expects this to be a small
-   number.  If you make it much bigger, you should probably tr yto
-   optimize the various routines to keep it sorted. */
+   number.  If you make it larger, you should probably optimize the
+   code below to keep it sorted. */
 #define LINE_NUMBER_RING_SIZE 8
 
 /* How much traversal has to be exceeded for two points to be
    considered "far" from each other.  When two points are far, cache
-   will be used.  You can set this to a small value for debugging
-   purposes.  */
-#define LINE_NUMBER_FAR 16384
+   will be used.  */
+#define LINE_NUMBER_FAR 32768
 
 /* How large a string has to be to give up searching it for newlines,
    before change. */
@@ -101,24 +98,23 @@
   narrow_line_number_cache (b);
 }
 
-/* Update line_number_begv, or flag it as dirty.  Do it only if the
-   line number cache is already initialized.  */
+/* Flag LINE_NUMBER_BEGV (b) as dirty.  Do it only if the line number
+   cache is already initialized.  */ 
 void
 narrow_line_number_cache (struct buffer *b)
 {
   if (NILP (b->line_number_cache))
     return;
-  /* Optimization: if BUF_BEG == BUF_BEGV (as is the case after Fwiden
-     and save_restriction_restore), don't bother calling scan_buffer.  */
+
   if (BUF_BEG (b) == BUF_BEGV (b))
-    {
-      LINE_NUMBER_BEGV (b) = Qzero;
-      return;
-    }
-  /* Calculating the line number of BUF_BEGV here is a bad idea,
-     because there is absolutely no reason to do it before the next
-     redisplay.  We simply mark it as dirty instead.  */
-  LINE_NUMBER_BEGV (b) = make_int (-1);
+    /* The is the case Fwiden and save_restriction_restore.  Since we
+       know the correct value, we can update it now.  */
+    LINE_NUMBER_BEGV (b) = Qzero;
+  else
+    /* Calculating the line number of BUF_BEGV here is a bad idea,
+       because there is absolutely no reason to do it before the next
+       redisplay.  We simply mark it as dirty instead.  */
+    LINE_NUMBER_BEGV (b) = make_int (-1);
 }
 
 /* Invalidate the line number cache positions that lie after POS. */
@@ -127,26 +123,24 @@
 {
   EMACS_INT i, j;
   Lisp_Object *ring = XVECTOR_DATA (LINE_NUMBER_RING (b));
-  Lisp_Object lisp_buffer = make_buffer (b);
 
   for (i = 0; i < LINE_NUMBER_RING_SIZE; i++)
     {
       if (!CONSP (ring[i]))
 	break;
       /* As the marker stays behind the insertions, this check might
-         as well be `>'.  However, Finsert_before_markers can move the
-         marker anyway, which bites in shell buffers.
+         as well be `>'.  However, Finsert_before_markers can advance
+         the marker anyway, which bites in shell buffers.
 
-	 #### This is wrong; it works right, but forces recreation of
-	 the cached marker (and recalculation of newlines) every time
-	 a newline is inserted at point, which is way losing.  Isn't
-	 there a way to make a marker impervious to
-	 Finsert_before_markers()??  Maybe I should convert to using
-	 extents.  */
+	 #### This forces recreation of the cached marker (and
+	 recalculation of newlines) every time a newline is inserted
+	 at point, which is way losing.  Isn't there a way to make a
+	 marker impervious to Finsert_before_markers()??  Maybe I
+	 should convert the code to use extents.  */
       if (marker_position (XCAR (ring[i])) >= pos)
 	{
 	  /* Get the marker out of the way.  */
-	  Fset_marker (XCAR (ring[i]), Qnil, lisp_buffer);
+	  Fset_marker (XCAR (ring[i]), Qnil, Qnil);
 	  /* ...and shift the ring elements, up to the first nil.  */
 	  for (j = i; !NILP (ring[j]) && j < LINE_NUMBER_RING_SIZE - 1; j++)
 	    ring[j] = ring[j + 1];
@@ -162,7 +156,7 @@
    than LINE_NUMBER_LARGE_STRING), invalidate the cache positions
    after POS without prior search.
 
-   This will do nothing, if cache is uninitialized.  */
+   This will do nothing if the cache is uninitialized.  */
 void
 insert_invalidate_line_number_cache (struct buffer *b, Bufpos pos,
 				     CONST Bufbyte *nonreloc, Bytecount length)
@@ -172,19 +166,19 @@
 
   if (length > LINE_NUMBER_LARGE_STRING
       ||
-      /* We could also count how many newlines are in the string, and
-         update the cache accordingly, but it would be too much work
-         for too little gain. */
+      /* We could also count how many newlines there are in the string
+         and update the cache accordingly, but it would be too much
+         work for too little gain. */
       memchr ((void *)nonreloc, '\n', (size_t) length))
     invalidate_line_number_cache (b, pos);
 }
 
 /* Invalidate the cache positions after FROM, if the region to be
-   deleted contains a newline.  If the region is too large (larger
-   than LINE_NUMBER_LARGE_STRING), invalidate the cache positions
-   after FROM without prior search.
+   deleted contains a newline.  If the region-to-be-deleted is larger
+   than LINE_NUMBER_LARGE_STRING, invalidate the cache positions after
+   FROM without unconditionally.
 
-   This will do nothing, if cache is uninitialized.  */
+   This will do nothing if the cache is uninitialized.  */
 void
 delete_invalidate_line_number_cache (struct buffer *b, Bufpos from, Bufpos to)
 {
@@ -215,22 +209,18 @@
 get_nearest_line_number (struct buffer *b, Bufpos *beg, Bufpos pos,
 			 EMACS_INT *line)
 {
+  EMACS_INT i;
   Lisp_Object *ring = XVECTOR_DATA (LINE_NUMBER_RING (b));
-  EMACS_INT i;
-  Charcount length, howfar;
-  Bufpos newpos;
+  Charcount length = pos - *beg;
 
-  length = pos - *beg;
   if (length < 0)
     length = -length;
 
-  /* Look for the nearest match. */
-  for (i = 0; i < LINE_NUMBER_RING_SIZE; i++)
+  /* Find the ring entry closest to POS, if it is closer than BEG. */
+  for (i = 0; i < LINE_NUMBER_RING_SIZE && CONSP (ring[i]); i++)
     {
-      if (!CONSP (ring[i]))
-	break;
-      newpos = marker_position (XCAR (ring[i]));
-      howfar = newpos - pos;
+      Bufpos newpos = marker_position (XCAR (ring[i]));
+      Charcount howfar = newpos - pos;
       if (howfar < 0)
 	howfar = -howfar;
       if (howfar < length)
@@ -242,19 +232,25 @@
     }
 }
 
-/* Add a (pos, line) pair to the ring, and rotate it. */
+/* Add a (POS . LINE) pair to the ring, and rotate it. */
 static void
-add_line_number (struct buffer *b, Bufpos pos, int line)
+add_position_to_cache (struct buffer *b, Bufpos pos, int line)
 {
   Lisp_Object *ring = XVECTOR_DATA (LINE_NUMBER_RING (b));
-  Lisp_Object marker;
-  int i;
+  int i = LINE_NUMBER_RING_SIZE - 1;
+
+  /* Set the last marker in the ring to point nowhere. */
+  if (CONSP (ring[i]))
+    Fset_marker (XCAR (ring[i]), Qnil, Qnil);
 
-  for (i = LINE_NUMBER_RING_SIZE - 1; i > 0; i--)
+  /* Rotate the ring... */
+  for (; i > 0; i--)
     ring[i] = ring[i - 1];
-  marker = Fmake_marker ();
-  Fset_marker (marker, make_int (pos), make_buffer (b));
-  ring[0] = Fcons (marker, make_int (line));
+
+  /* ...and update it. */
+  ring[0] = Fcons (Fset_marker (Fmake_marker (), make_int (pos),
+				make_buffer (b)),
+		   make_int (line));
 }
 
 /* Calculate the line number in buffer B at position POS.  If CACHEP
@@ -272,7 +268,7 @@
    appropriately.
 
    If the calculation (with or without the cache lookup) required more
-   than LINE_NUMBER_FAR bytes of traversal, update the cache.  */
+   than LINE_NUMBER_FAR characters of traversal, update the cache.  */
 EMACS_INT
 buffer_line_number (struct buffer *b, Bufpos pos, int cachep)
 {
@@ -314,12 +310,11 @@
     {
       /* If too far, update the cache. */
       if ((pos > beg ? pos - beg : beg - pos) > LINE_NUMBER_FAR)
-	add_line_number (b, pos, line);
-      /* Account for narrowing.  If CACHEP is nil, this is
+	add_position_to_cache (b, pos, line);
+      /* Account for narrowing.  If cache is not used, this is
 	 unnecessary, because we counted from BUF_BEGV anyway.  */
       line -= XINT (LINE_NUMBER_BEGV (b));
     }
 
   return line;
 }
-