Björn Steinbrink wrote:
> Using ":syn sync fromstart" on platforms where "long" is 64bits wide
> breaks the state cache, causing vim to be very very slow on large files.
>
> How to reproduce:
> :syntax on
> :help :syn-sync
> :syn sync fromstart
> <scroll up using j>
>
> Here's what happens:
>
> When ":syn sync fromstart" is used, vim sets minlines to MAXLNUM, which
> is defined as the largest positive signed 32 bit number, 0x7fffffff.
>
> When the help buffer is opened, vim jumps to line 3826 and there is
> either no valid state yet or it is too far away from this line (I didn't
> check which case it is, as it doesn't matter), so in syntax.c:559, we
> find that our current state is invalid and thus do:
>
> syn_sync(wp, lnum, last_valid);
> first_stored = current_lnum + syn_block->b_syn_sync_minlines;
>
> syn_sync() will set current_lnum to 1, so we sync from the start. And
> b_syn_sync_minlines is 0x7fffffff.
>
> Now, on a platform where long is 32bits, the addition happens to
> overflow[1], i.e. we get some large negative value, but on a platform
> with 64bit "long"s, no such overflow happens and we get a large positive
> number.
>
> Then, a few lines further down, we check whether the current state is
> valid, starting with line 583:
>
> /* If we parsed at least "minlines" lines or started at a valid
> * state, the current state is considered valid. */
> if (current_lnum >= first_stored)
>
> With 32bit longs, first_stored overflowed, so it's negative and the
> check always succeeds. With 64bit longs, first_stored is a large
> positive number, and the check will (practically) never succeed, so the
> state is never stored in the cache.
>
> The patch below[2] is a quick hack that eliminates the problem, but
> spreads knowledge about the MAXLNUM "shortcut" for the fromstart syncing
> through the code, so IMHO that's not an acceptable solution, but I
> currently lack time and knowledge to come up with anything more useful.
>
> Regards,
> Björn
>
> [1] AFAIK, signed integer overflow is undefined in standard C. So while
> you could just adjust MAXLNUM to be 2^63-1 for 64bit longs, that's not a
> true "solution" either. One rather wants to get rid of the overflow.
>
> [2]
> diff --git a/src/syntax.c b/src/syntax.c
> index a9a2e86..2288f54 100644
> --- a/src/syntax.c
> +++ b/src/syntax.c
> @@ -559,7 +559,7 @@ syntax_start(wp, lnum)
> if (INVALID_STATE(¤t_state))
> {
> syn_sync(wp, lnum, last_valid);
> - first_stored = current_lnum + syn_block->b_syn_sync_minlines;
> + first_stored = current_lnum + (syn_block->b_syn_sync_minlines ==
> MAXLNUM ? 0 : syn_block->b_syn_sync_minlines);
> }
> else
> first_stored = current_lnum;
Thanks for the clear explanation and the patch. I'll see if I can think
of a nicer solution, otherwise I might just include this fix.
--
hundred-and-one symptoms of being an internet addict:
178. You look for an icon to double-click to open your bedroom window.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php