Hi,
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;
--
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