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(&current_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

Raspunde prin e-mail lui