]> granicus.if.org Git - vim/commitdiff
patch 8.1.0958: compiling weird regexp pattern is very slow v8.1.0958
authorBram Moolenaar <Bram@vim.org>
Wed, 20 Feb 2019 21:04:32 +0000 (22:04 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 20 Feb 2019 21:04:32 +0000 (22:04 +0100)
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.

src/eval.c
src/regexp_nfa.c
src/testdir/test_assert.vim
src/testdir/test_regexp_latin.vim
src/version.c

index f66d2965024ba513b344b362df3e1f3764e3ee1e..046688f0b8288a1fdba93f1b092f872baa141459 100644 (file)
@@ -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)
        {
index 9633791bcf4f8c3003e4d9797ced0b02ea58b4ef..333c006f4842a7c1b605bbde4ee5ae38c7279981 100644 (file)
@@ -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;
index 298a6db15a891f0a1dd99841c2a85a01bd87cf4a..7df641c6a4d4be3cadafce4870498da2d4023c33 100644 (file)
@@ -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()
index d603acdbcef7d2838abf2607219bf8ce6c28b069..7a4d98f9ada87c68dfe6d7b517e23f0bf781b1d0 100644 (file)
@@ -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
index 5a3a53c38447df2789a91ddb74df7a8069bc5527..b2d76b7529ee8df62635df233ba0171c2715b3a1 100644 (file)
@@ -779,6 +779,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    958,
 /**/
     957,
 /**/