summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-02-20 22:04:32 +0100
committerBram Moolenaar <Bram@vim.org>2019-02-20 22:04:32 +0100
commit38f08e76acf7d21bb34cf8f79f0f82eb63cdc987 (patch)
treeaa303c467edd65762eb39e19843d8112f035f164
parent35856718881834a76225530d502c68fdec6584cf (diff)
downloadvim-git-38f08e76acf7d21bb34cf8f79f0f82eb63cdc987.tar.gz
patch 8.1.0958: compiling weird regexp pattern is very slowv8.1.0958
Problem: Compiling weird regexp pattern is very slow. Solution: When reallocating post list increase size by 50%. (Kuang-che Wu, closes #4012) Make assert_inrange() accept float values.
-rw-r--r--src/eval.c75
-rw-r--r--src/regexp_nfa.c5
-rw-r--r--src/testdir/test_assert.vim16
-rw-r--r--src/testdir/test_regexp_latin.vim11
-rw-r--r--src/version.c2
5 files changed, 84 insertions, 25 deletions
diff --git a/src/eval.c b/src/eval.c
index f66d29650..046688f0b 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -9365,32 +9365,65 @@ assert_inrange(typval_T *argvars)
{
garray_T ga;
int error = FALSE;
- varnumber_T lower = tv_get_number_chk(&argvars[0], &error);
- varnumber_T upper = tv_get_number_chk(&argvars[1], &error);
- varnumber_T actual = tv_get_number_chk(&argvars[2], &error);
char_u *tofree;
char msg[200];
char_u numbuf[NUMBUFLEN];
- if (error)
- return 0;
- if (actual < lower || actual > upper)
+#ifdef FEAT_FLOAT
+ if (argvars[0].v_type == VAR_FLOAT
+ || argvars[1].v_type == VAR_FLOAT
+ || argvars[2].v_type == VAR_FLOAT)
{
- prepare_assert_error(&ga);
- if (argvars[3].v_type != VAR_UNKNOWN)
+ float_T flower = tv_get_float(&argvars[0]);
+ float_T fupper = tv_get_float(&argvars[1]);
+ float_T factual = tv_get_float(&argvars[2]);
+
+ if (factual < flower || factual > fupper)
{
- ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
- vim_free(tofree);
+ prepare_assert_error(&ga);
+ if (argvars[3].v_type != VAR_UNKNOWN)
+ {
+ ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
+ vim_free(tofree);
+ }
+ else
+ {
+ vim_snprintf(msg, 200, "Expected range %g - %g, but got %g",
+ flower, fupper, factual);
+ ga_concat(&ga, (char_u *)msg);
+ }
+ assert_error(&ga);
+ ga_clear(&ga);
+ return 1;
}
- else
+ }
+ else
+#endif
+ {
+ varnumber_T lower = tv_get_number_chk(&argvars[0], &error);
+ varnumber_T upper = tv_get_number_chk(&argvars[1], &error);
+ varnumber_T actual = tv_get_number_chk(&argvars[2], &error);
+
+ if (error)
+ return 0;
+ if (actual < lower || actual > upper)
{
- vim_snprintf(msg, 200, "Expected range %ld - %ld, but got %ld",
+ prepare_assert_error(&ga);
+ if (argvars[3].v_type != VAR_UNKNOWN)
+ {
+ ga_concat(&ga, tv2string(&argvars[3], &tofree, numbuf, 0));
+ vim_free(tofree);
+ }
+ else
+ {
+ vim_snprintf(msg, 200, "Expected range %ld - %ld, but got %ld",
(long)lower, (long)upper, (long)actual);
- ga_concat(&ga, (char_u *)msg);
+ ga_concat(&ga, (char_u *)msg);
+ }
+ assert_error(&ga);
+ ga_clear(&ga);
+ return 1;
}
- assert_error(&ga);
- ga_clear(&ga);
- return 1;
}
return 0;
}
@@ -9822,14 +9855,8 @@ typval_compare(
{
float_T f1, f2;
- if (typ1->v_type == VAR_FLOAT)
- f1 = typ1->vval.v_float;
- else
- f1 = tv_get_number(typ1);
- if (typ2->v_type == VAR_FLOAT)
- f2 = typ2->vval.v_float;
- else
- f2 = tv_get_number(typ2);
+ f1 = tv_get_float(typ1);
+ f2 = tv_get_float(typ2);
n1 = FALSE;
switch (type)
{
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
index 9633791bc..333c006f4 100644
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -509,10 +509,13 @@ nfa_get_match_text(nfa_state_T *start)
realloc_post_list(void)
{
int nstate_max = (int)(post_end - post_start);
- int new_max = nstate_max + 1000;
+ int new_max;
int *new_start;
int *old_start;
+ // For weird patterns the number of states can be very high. Increasing by
+ // 50% seems a reasonable compromise between memory use and speed.
+ new_max = nstate_max * 3 / 2;
new_start = (int *)lalloc(new_max * sizeof(int), TRUE);
if (new_start == NULL)
return FAIL;
diff --git a/src/testdir/test_assert.vim b/src/testdir/test_assert.vim
index 298a6db15..7df641c6a 100644
--- a/src/testdir/test_assert.vim
+++ b/src/testdir/test_assert.vim
@@ -190,6 +190,22 @@ func Test_assert_inrange()
call remove(v:errors, 0)
call assert_fails('call assert_inrange(1, 1)', 'E119:')
+
+ if has('float')
+ call assert_equal(0, assert_inrange(7.0, 7, 7))
+ call assert_equal(0, assert_inrange(7, 7.0, 7))
+ call assert_equal(0, assert_inrange(7, 7, 7.0))
+ call assert_equal(0, assert_inrange(5, 7, 5.0))
+ call assert_equal(0, assert_inrange(5, 7, 6.0))
+ call assert_equal(0, assert_inrange(5, 7, 7.0))
+
+ call assert_equal(1, assert_inrange(5, 7, 4.0))
+ call assert_match("Expected range 5.0 - 7.0, but got 4.0", v:errors[0])
+ call remove(v:errors, 0)
+ call assert_equal(1, assert_inrange(5, 7, 8.0))
+ call assert_match("Expected range 5.0 - 7.0, but got 8.0", v:errors[0])
+ call remove(v:errors, 0)
+ endif
endfunc
func Test_assert_with_msg()
diff --git a/src/testdir/test_regexp_latin.vim b/src/testdir/test_regexp_latin.vim
index d603acdbc..7a4d98f9a 100644
--- a/src/testdir/test_regexp_latin.vim
+++ b/src/testdir/test_regexp_latin.vim
@@ -130,3 +130,14 @@ func Test_range_with_newline()
call assert_equal(0, search("[ -*\\t-\\n]"))
bwipe!
endfunc
+
+func Test_pattern_compile_speed()
+ if !exists('+spellcapcheck') || !has('reltime')
+ return
+ endif
+ let start = reltime()
+ " this used to be very slow, not it should be about a second
+ set spc=\\v(((((Nxxxxxxx&&xxxx){179})+)+)+){179}
+ call assert_inrange(0.01, 10.0, reltimefloat(reltime(start)))
+ set spc=
+endfunc
diff --git a/src/version.c b/src/version.c
index 5a3a53c38..b2d76b752 100644
--- a/src/version.c
+++ b/src/version.c
@@ -780,6 +780,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 958,
+/**/
957,
/**/
956,