Subject: Re: bug#16526: 24.3.50; scroll-conservatively & c-mode regression

From: Alan Mackenzie <[email-masked]>
Date: Sun, 26 Jan 2014 20:43:10 +0000

Hi, Eli.

On Sun, Jan 26, 2014 at 07:20:27PM +0200, Eli Zaretskii wrote:

> You are right, sorry.  (I wasn't wrong, either: recenter does call the
> same find_defun_start around EOB, which is what I saw.  But those
> calls are very few and aren't responsible for the slowdown.  I also
> wasn't wrong about point being at EOB, see below.  But I described
> what happens incorrectly.)

> Here's what I see in the debugger:

> After beginning-of-buffer jumps to point-min, redisplay kicks in.
> Since scroll-conservatively is set to a large value, redisplay first
> tries to see whether it can bring point into view by scrolling the
> window as little as possible.  It calls try_scrolling, which at some
> point (around line 15000) tries to see whether the new location of
> point is close enough to the current window start.  It does so by
> calling move_it_to, which simulates the display.  While doing so,
> move_it_to hits a portion of text with font-lock properties, and calls
> JIT Lock to fontify them.

> And here's where things go awry: For some reason, the CC Mode
> fontification code decides it needs to scan the buffer backwards,
> starting from EOB.

The @dfn{state cache}, a list of certain brace/paren/bracket positions
around some position, is set for a position near EOB.  With the switch to
a different position, CC Mode tweaks the state cache rather than
calculating it anew starting at BOB.  When the new position is nearer
BOB, the code searches backwards for the appropriate braces.  However, it
shouldn't be scanning the entire buffer backwards.  There is clearly a
bug here.

> So it goes temporarily to EOB (this is why I saw point being there),
> and scans all the way back, I think in this loop from
> c-append-lower-brace-pair-to-state-cache, which is called with its
> first argument FROM set to EOB:

> 	  ;; In the next pair of nested loops, the inner one moves back past a
> 	  ;; pair of (mis-)matching parens or brackets; the outer one moves
> 	  ;; back over a sequence of unmatched close brace/paren/bracket each
> 	  ;; time round.
> 	  (while
> 	      (progn
> 		(c-safe
> 		  (while
> 		      (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; might signal
> 			   (setq bra (scan-lists ce -1 1)) ; back past (/[/{; might signal
> 			   (or (> bra here) ;(> ce here)
> 			       (and
> 				(< ce here)
> 				(or (not (eq (char-after bra) ?\{))
> 				    (and (goto-char bra)
> 					 (c-beginning-of-macro)
> 					 (< (point) macro-start-or-from))))))))
> 		(and ce (< ce bra)))
> 	    (setq bra ce))	; If we just backed over an unbalanced closing
> 					; brace, ignore it.

The backward scan-lists calls will be causing continual forward searches
from BOB in syntax.c, every time the backward scan hits a comment ender.

> This loop takes a lot of time, of course, and is a waste of time,
> since eventually try_scrolling comes to the correct conclusion that
> scrolling is impossible, and instead recenters at BOB.

> Why does CC Mode decide to go from EOB backwards, I don't know;
> presumably, this is decided by c-parse-state-get-strategy as part of
> c-parse-state-1.

Yes.  There is a bug here.  I have a strong suspicion where.

[ .... ]

> I hope this information will allow Alan to find the culprit and solve
> the problem.

Yes indeed, thanks.  But I'm not going to be able to resolve it in a
scale of hours.  It's going to be days.  Sorry!

-- 
Alan Mackenzie (Nuremberg, Germany).