]> granicus.if.org Git - vim/commitdiff
patch 8.2.0751: Vim9: performance can be improved v8.2.0751
authorBram Moolenaar <Bram@vim.org>
Wed, 13 May 2020 20:44:22 +0000 (22:44 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 13 May 2020 20:44:22 +0000 (22:44 +0200)
Problem:    Vim9: performance can be improved.
Solution:   Don't call break.  Inline check for list materialize.  Make an
            inline version of ga_grow().

17 files changed:
src/channel.c
src/eval.c
src/evalbuffer.c
src/evalfunc.c
src/evalvars.c
src/filepath.c
src/highlight.c
src/if_py_both.h
src/insexpand.c
src/json.c
src/list.c
src/macros.h
src/misc2.c
src/popupmenu.c
src/popupwin.c
src/proto/misc2.pro
src/userfunc.c

index 1fcb8451cbf0cc10550430e9b239c7fe86b97b06..68adbc37821e840278b65d0e84abca2225b9cf25 100644 (file)
@@ -2399,7 +2399,7 @@ channel_get_json(
        list_T      *l = item->jq_value->vval.v_list;
        typval_T    *tv;
 
-       range_list_materialize(l);
+       CHECK_LIST_MATERIALIZE(l);
        tv = &l->lv_first->li_tv;
 
        if ((without_callback || !item->jq_no_callback)
@@ -5302,7 +5302,7 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported, int supported2)
                    return FAIL;
                }
 
-               range_list_materialize(item->vval.v_list);
+               CHECK_LIST_MATERIALIZE(item->vval.v_list);
                li = item->vval.v_list->lv_first;
                for (; li != NULL && n < 16; li = li->li_next, n++)
                {
@@ -5729,7 +5729,7 @@ win32_build_cmd(list_T *l, garray_T *gap)
     listitem_T  *li;
     char_u     *s;
 
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     FOR_ALL_LIST_ITEMS(l, li)
     {
        s = tv_get_string_chk(&li->li_tv);
index b7003a882cc2ff40ac8d60fccce74ee04ed80a6a..2100d8039feb115a3f14bcf248f5dc120744af02 100644 (file)
@@ -1449,7 +1449,7 @@ eval_for_line(
                else
                {
                    // Need a real list here.
-                   range_list_materialize(l);
+                   CHECK_LIST_MATERIALIZE(l);
 
                    // No need to increment the refcount, it's already set for
                    // the list being used in "tv".
index f11727c78713a013665e67cc096a7755715771f2..adbbca3f7b66010f4f62d6eb1920c6f2fa624d82 100644 (file)
@@ -183,7 +183,7 @@ set_buffer_lines(
                rettv->vval.v_number = 1;       // FAIL
            goto done;
        }
-       range_list_materialize(l);
+       CHECK_LIST_MATERIALIZE(l);
        li = l->lv_first;
     }
     else
index c499890d9b192f2be93ee1daf7fb336963badafb..7579208359b20e3614898ab2eac368ec08306a1f 100644 (file)
@@ -2275,7 +2275,7 @@ execute_common(typval_T *argvars, typval_T *rettv, int arg_off)
     {
        listitem_T      *item;
 
-       range_list_materialize(list);
+       CHECK_LIST_MATERIALIZE(list);
        item = list->lv_first;
        do_cmdline(NULL, get_list_line, (void *)&item,
                      DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT|DOCMD_KEYTYPED);
@@ -2820,7 +2820,7 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
                        copy_tv(&arg_pt->pt_argv[i], &pt->pt_argv[i]);
                    if (lv_len > 0)
                    {
-                       range_list_materialize(list);
+                       CHECK_LIST_MATERIALIZE(list);
                        FOR_ALL_LIST_ITEMS(list, li)
                            copy_tv(&li->li_tv, &pt->pt_argv[i++]);
                    }
@@ -4912,7 +4912,7 @@ f_index(typval_T *argvars, typval_T *rettv)
     l = argvars[0].vval.v_list;
     if (l != NULL)
     {
-       range_list_materialize(l);
+       CHECK_LIST_MATERIALIZE(l);
        item = l->lv_first;
        if (argvars[2].v_type != VAR_UNKNOWN)
        {
@@ -5018,7 +5018,7 @@ f_inputlist(typval_T *argvars, typval_T *rettv)
     msg_clr_eos();
 
     l = argvars[0].vval.v_list;
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     FOR_ALL_LIST_ITEMS(l, li)
     {
        msg_puts((char *)tv_get_string(&li->li_tv));
@@ -5494,7 +5494,7 @@ find_some_match(typval_T *argvars, typval_T *rettv, matchtype_T type)
     {
        if ((l = argvars[0].vval.v_list) == NULL)
            goto theend;
-       range_list_materialize(l);
+       CHECK_LIST_MATERIALIZE(l);
        li = l->lv_first;
     }
     else
@@ -6279,7 +6279,7 @@ f_range(typval_T *argvars, typval_T *rettv)
        list_T *list = rettv->vval.v_list;
 
        // Create a non-materialized list.  This is much more efficient and
-       // works with ":for".  If used otherwise range_list_materialize() must
+       // works with ":for".  If used otherwise CHECK_LIST_MATERIALIZE() must
        // be called.
        list->lv_first = &range_list_item;
        list->lv_u.nonmat.lv_start = start;
@@ -6290,26 +6290,24 @@ f_range(typval_T *argvars, typval_T *rettv)
 }
 
 /*
- * If "list" is a non-materialized list then materialize it now.
+ * Materialize "list".
+ * Do not call directly, use CHECK_LIST_MATERIALIZE()
  */
     void
 range_list_materialize(list_T *list)
 {
-    if (list->lv_first == &range_list_item)
-    {
-       varnumber_T start = list->lv_u.nonmat.lv_start;
-       varnumber_T end = list->lv_u.nonmat.lv_end;
-       int         stride = list->lv_u.nonmat.lv_stride;
-       varnumber_T i;
-
-       list->lv_first = NULL;
-       list->lv_u.mat.lv_last = NULL;
-       list->lv_len = 0;
-       list->lv_u.mat.lv_idx_item = NULL;
-       for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
-           if (list_append_number(list, (varnumber_T)i) == FAIL)
-               break;
-    }
+    varnumber_T start = list->lv_u.nonmat.lv_start;
+    varnumber_T end = list->lv_u.nonmat.lv_end;
+    int            stride = list->lv_u.nonmat.lv_stride;
+    varnumber_T i;
+
+    list->lv_first = NULL;
+    list->lv_u.mat.lv_last = NULL;
+    list->lv_len = 0;
+    list->lv_u.mat.lv_idx_item = NULL;
+    for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
+       if (list_append_number(list, (varnumber_T)i) == FAIL)
+           break;
 }
 
     static void
@@ -7327,7 +7325,7 @@ f_setreg(typval_T *argvars, typval_T *rettv)
 
        if (ll != NULL)
        {
-           range_list_materialize(ll);
+           CHECK_LIST_MATERIALIZE(ll);
            FOR_ALL_LIST_ITEMS(ll, li)
            {
                strval = tv_get_string_buf_chk(&li->li_tv, buf);
index 01aef1ae69dbd303458f89e2ba4dc5cdcd16232e..e747230033330ee4a785c0efa9b4f2e0b245532b 100644 (file)
@@ -863,7 +863,7 @@ ex_let_vars(
        return FAIL;
     }
 
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     item = l->lv_first;
     while (*arg != ']')
     {
index 81f90c3392d971c94ffd288b226d430c9fb05dee..27a26e5edc161032d305cd0625eda844e106fc77 100644 (file)
@@ -1917,7 +1917,7 @@ f_writefile(typval_T *argvars, typval_T *rettv)
        list = argvars[0].vval.v_list;
        if (list == NULL)
            return;
-       range_list_materialize(list);
+       CHECK_LIST_MATERIALIZE(list);
        FOR_ALL_LIST_ITEMS(list, li)
            if (tv_get_string_chk(&li->li_tv) == NULL)
                return;
index 64f37a4e8d61c1828d816cfa45fa665a80e99510..7a7e537f382095a73b40e62558b11523245ae573 100644 (file)
@@ -3743,7 +3743,7 @@ match_add(
        listitem_T      *li;
        int             i;
 
-       range_list_materialize(pos_list);
+       CHECK_LIST_MATERIALIZE(pos_list);
        for (i = 0, li = pos_list->lv_first; li != NULL && i < MAXPOSMATCH;
                                                        i++, li = li->li_next)
        {
index a13a5e345a77a86177552840cca988954109b630..9f563f0afd3fd465c3f8e2d562d7206b27b54b71 100644 (file)
@@ -785,7 +785,7 @@ VimToPython(typval_T *our_tv, int depth, PyObject *lookup_dict)
            return NULL;
        }
 
-       range_list_materialize(list);
+       CHECK_LIST_MATERIALIZE(list);
        FOR_ALL_LIST_ITEMS(list, curr)
        {
            if (!(newObj = VimToPython(&curr->li_tv, depth + 1, lookup_dict)))
@@ -2256,7 +2256,7 @@ ListNew(PyTypeObject *subtype, list_T *list)
        return NULL;
     self->list = list;
     ++list->lv_refcount;
-    range_list_materialize(list);
+    CHECK_LIST_MATERIALIZE(list);
 
     pyll_add((PyObject *)(self), &self->ref, &lastlist);
 
@@ -2824,7 +2824,7 @@ ListIter(ListObject *self)
        return NULL;
     }
 
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     list_add_watch(l, &lii->lw);
     lii->lw.lw_item = l->lv_first;
     lii->list = l;
@@ -3021,7 +3021,7 @@ FunctionConstructor(PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
                return NULL;
            }
            argslist = argstv.vval.v_list;
-           range_list_materialize(argslist);
+           CHECK_LIST_MATERIALIZE(argslist);
 
            argc = argslist->lv_len;
            if (argc != 0)
index bd809b0e6ffa9bcb1e3f71045a2050acefdec412..6963baf9874002dc407b4a0f5282f692e2fd6a07 100644 (file)
@@ -2334,7 +2334,7 @@ ins_compl_add_list(list_T *list)
     int                dir = compl_direction;
 
     // Go through the List with matches and add each of them.
-    range_list_materialize(list);
+    CHECK_LIST_MATERIALIZE(list);
     FOR_ALL_LIST_ITEMS(list, li)
     {
        if (ins_compl_add_tv(&li->li_tv, dir) == OK)
@@ -2519,7 +2519,7 @@ get_complete_info(list_T *what_list, dict_T *retdict)
     else
     {
        what_flag = 0;
-       range_list_materialize(what_list);
+       CHECK_LIST_MATERIALIZE(what_list);
        FOR_ALL_LIST_ITEMS(what_list, item)
        {
            char_u *what = tv_get_string(&item->li_tv);
index c1c6e85638846eedcb54fe2d1428b1c1836120e8..ec3355e714c8ae9f6f975720c23c991c4ace0d2e 100644 (file)
@@ -265,7 +265,7 @@ json_encode_item(garray_T *gap, typval_T *val, int copyID, int options)
 
                    l->lv_copyID = copyID;
                    ga_append(gap, '[');
-                   range_list_materialize(l);
+                   CHECK_LIST_MATERIALIZE(l);
                    for (li = l->lv_first; li != NULL && !got_int; )
                    {
                        if (json_encode_item(gap, &li->li_tv, copyID,
index eb76cc6831c9287d154fa5260f27a1d2abc7a752..6242e5243805f7d08f198cb32b2b9b57f5befd63 100644 (file)
@@ -378,8 +378,8 @@ list_equal(
     if (l1 == NULL || l2 == NULL)
        return FALSE;
 
-    range_list_materialize(l1);
-    range_list_materialize(l2);
+    CHECK_LIST_MATERIALIZE(l1);
+    CHECK_LIST_MATERIALIZE(l2);
 
     for (item1 = l1->lv_first, item2 = l2->lv_first;
            item1 != NULL && item2 != NULL;
@@ -411,7 +411,7 @@ list_find(list_T *l, long n)
     if (n < 0 || n >= l->lv_len)
        return NULL;
 
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
 
     // When there is a cached index may start search from there.
     if (l->lv_u.mat.lv_idx_item != NULL)
@@ -541,7 +541,7 @@ list_idx_of_item(list_T *l, listitem_T *item)
 
     if (l == NULL)
        return -1;
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     idx = 0;
     for (li = l->lv_first; li != NULL && li != item; li = li->li_next)
        ++idx;
@@ -556,7 +556,7 @@ list_idx_of_item(list_T *l, listitem_T *item)
     void
 list_append(list_T *l, listitem_T *item)
 {
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     if (l->lv_u.mat.lv_last == NULL)
     {
        // empty list
@@ -706,7 +706,7 @@ list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
     void
 list_insert(list_T *l, listitem_T *ni, listitem_T *item)
 {
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     if (item == NULL)
        // Append new item at end of list.
        list_append(l, ni);
@@ -741,8 +741,8 @@ list_extend(list_T *l1, list_T *l2, listitem_T *bef)
     listitem_T *item;
     int                todo = l2->lv_len;
 
-    range_list_materialize(l1);
-    range_list_materialize(l2);
+    CHECK_LIST_MATERIALIZE(l1);
+    CHECK_LIST_MATERIALIZE(l2);
 
     // We also quit the loop when we have inserted the original item count of
     // the list, avoid a hang when we extend a list with itself.
@@ -801,7 +801,7 @@ list_copy(list_T *orig, int deep, int copyID)
            orig->lv_copyID = copyID;
            orig->lv_copylist = copy;
        }
-       range_list_materialize(orig);
+       CHECK_LIST_MATERIALIZE(orig);
        for (item = orig->lv_first; item != NULL && !got_int;
                                                         item = item->li_next)
        {
@@ -842,7 +842,7 @@ vimlist_remove(list_T *l, listitem_T *item, listitem_T *item2)
 {
     listitem_T *ip;
 
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
 
     // notify watchers
     for (ip = item; ip != NULL; ip = ip->li_next)
@@ -877,7 +877,7 @@ list2string(typval_T *tv, int copyID, int restore_copyID)
        return NULL;
     ga_init2(&ga, (int)sizeof(char), 80);
     ga_append(&ga, '[');
-    range_list_materialize(tv->vval.v_list);
+    CHECK_LIST_MATERIALIZE(tv->vval.v_list);
     if (list_join(&ga, tv->vval.v_list, (char_u *)", ",
                                       FALSE, restore_copyID, copyID) == FAIL)
     {
@@ -915,7 +915,7 @@ list_join_inner(
     char_u     *s;
 
     // Stringify each item in the list.
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     for (item = l->lv_first; item != NULL && !got_int; item = item->li_next)
     {
        s = echo_string_core(&item->li_tv, &tofree, numbuf, copyID,
@@ -1116,7 +1116,7 @@ write_list(FILE *fd, list_T *list, int binary)
     int                ret = OK;
     char_u     *s;
 
-    range_list_materialize(list);
+    CHECK_LIST_MATERIALIZE(list);
     FOR_ALL_LIST_ITEMS(list, li)
     {
        for (s = tv_get_string(&li->li_tv); *s != NUL; ++s)
@@ -1203,7 +1203,7 @@ f_list2str(typval_T *argvars, typval_T *rettv)
     if (argvars[1].v_type != VAR_UNKNOWN)
        utf8 = (int)tv_get_number_chk(&argvars[1], NULL);
 
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     ga_init2(&ga, 1, 80);
     if (has_mbyte || utf8)
     {
@@ -1496,7 +1496,7 @@ do_sort_uniq(typval_T *argvars, typval_T *rettv, int sort)
                                                                        TRUE))
            goto theend;
        rettv_list_set(rettv, l);
-       range_list_materialize(l);
+       CHECK_LIST_MATERIALIZE(l);
 
        len = list_len(l);
        if (len <= 1)
@@ -1873,7 +1873,7 @@ filter_map(typval_T *argvars, typval_T *rettv, int map)
            // set_vim_var_nr() doesn't set the type
            set_vim_var_type(VV_KEY, VAR_NUMBER);
 
-           range_list_materialize(l);
+           CHECK_LIST_MATERIALIZE(l);
            if (map && l->lv_lock == 0)
                l->lv_lock = VAR_LOCKED;
            for (li = l->lv_first; li != NULL; li = nli)
@@ -2011,7 +2011,7 @@ f_count(typval_T *argvars, typval_T *rettv)
 
        if ((l = argvars[0].vval.v_list) != NULL)
        {
-           range_list_materialize(l);
+           CHECK_LIST_MATERIALIZE(l);
            li = l->lv_first;
            if (argvars[2].v_type != VAR_UNKNOWN)
            {
index 9a3d4e13cf3934808b9a32f2a8abd2c04fdb8278..2ac705d4a1caadbd979eb00015761da7ba1fe13c 100644 (file)
 # define ESTACK_CHECK_NOW
 # define CHECK_CURBUF
 #endif
+
+// Inline the condition for performance.
+#define CHECK_LIST_MATERIALIZE(l) if ((l)->lv_first == &range_list_item) range_list_materialize(l)
+
+// Inlined version of ga_grow().  Especially useful if "n" is a constant.
+#define GA_GROW(gap, n) (((gap)->ga_maxlen - (gap)->ga_len < n) ? ga_grow_inner((gap), (n)) : OK)
index 50efde7f7bd740873566fa61ed4d13bc7bf62c24..678b73c009dcb02ff2b4e2951c631b5bd12a9608 100644 (file)
@@ -2053,31 +2053,36 @@ ga_init2(garray_T *gap, int itemsize, int growsize)
  */
     int
 ga_grow(garray_T *gap, int n)
+{
+    if (gap->ga_maxlen - gap->ga_len < n)
+       return ga_grow_inner(gap, n);
+    return OK;
+}
+
+    int
+ga_grow_inner(garray_T *gap, int n)
 {
     size_t     old_len;
     size_t     new_len;
     char_u     *pp;
 
-    if (gap->ga_maxlen - gap->ga_len < n)
-    {
-       if (n < gap->ga_growsize)
-           n = gap->ga_growsize;
-
-       // A linear growth is very inefficient when the array grows big.  This
-       // is a compromise between allocating memory that won't be used and too
-       // many copy operations. A factor of 1.5 seems reasonable.
-       if (n < gap->ga_len / 2)
-           n = gap->ga_len / 2;
-
-       new_len = gap->ga_itemsize * (gap->ga_len + n);
-       pp = vim_realloc(gap->ga_data, new_len);
-       if (pp == NULL)
-           return FAIL;
-       old_len = gap->ga_itemsize * gap->ga_maxlen;
-       vim_memset(pp + old_len, 0, new_len - old_len);
-       gap->ga_maxlen = gap->ga_len + n;
-       gap->ga_data = pp;
-    }
+    if (n < gap->ga_growsize)
+       n = gap->ga_growsize;
+
+    // A linear growth is very inefficient when the array grows big.  This
+    // is a compromise between allocating memory that won't be used and too
+    // many copy operations. A factor of 1.5 seems reasonable.
+    if (n < gap->ga_len / 2)
+       n = gap->ga_len / 2;
+
+    new_len = gap->ga_itemsize * (gap->ga_len + n);
+    pp = vim_realloc(gap->ga_data, new_len);
+    if (pp == NULL)
+       return FAIL;
+    old_len = gap->ga_itemsize * gap->ga_maxlen;
+    vim_memset(pp + old_len, 0, new_len - old_len);
+    gap->ga_maxlen = gap->ga_len + n;
+    gap->ga_data = pp;
     return OK;
 }
 
index d6993dc433ebc96b73797f2f8a6f4b9a1a213402..2fe4cff402b0199aa971253048e894eab7ece085 100644 (file)
@@ -1318,7 +1318,7 @@ ui_post_balloon(char_u *mesg, list_T *list)
        balloon_array = ALLOC_CLEAR_MULT(pumitem_T, list->lv_len);
        if (balloon_array == NULL)
            return;
-       range_list_materialize(list);
+       CHECK_LIST_MATERIALIZE(list);
        for (idx = 0, li = list->lv_first; li != NULL; li = li->li_next, ++idx)
        {
            char_u *text = tv_get_string_chk(&li->li_tv);
index a244c32368f6996eceac6ae12ea1d8de7dfaedc5..4ee097a066987057ffc47c5231a45a0c4e3365fc 100644 (file)
@@ -98,7 +98,7 @@ set_padding_border(dict_T *dict, int *array, char *name, int max_val)
                array[i] = 1;
            if (list != NULL)
            {
-               range_list_materialize(list);
+               CHECK_LIST_MATERIALIZE(list);
                for (i = 0, li = list->lv_first; i < 4 && i < list->lv_len;
                                                         ++i, li = li->li_next)
                {
@@ -516,7 +516,7 @@ handle_moved_argument(win_T *wp, dictitem_T *di, int mousemoved)
        int         mincol;
        int         maxcol;
 
-       range_list_materialize(l);
+       CHECK_LIST_MATERIALIZE(l);
        li = l->lv_first;
        if (l->lv_len == 3)
        {
@@ -756,7 +756,7 @@ apply_general_options(win_T *wp, dict_T *dict)
            listitem_T  *li;
            int         i;
 
-           range_list_materialize(list);
+           CHECK_LIST_MATERIALIZE(list);
            for (i = 0, li = list->lv_first; i < 4 && i < list->lv_len;
                                                     ++i, li = li->li_next)
            {
@@ -790,7 +790,7 @@ apply_general_options(win_T *wp, dict_T *dict)
 
            if (list != NULL)
            {
-               range_list_materialize(list);
+               CHECK_LIST_MATERIALIZE(list);
                for (i = 0, li = list->lv_first; i < 8 && i < list->lv_len;
                                                         ++i, li = li->li_next)
                {
@@ -845,7 +845,7 @@ apply_general_options(win_T *wp, dict_T *dict)
                    break;
                }
                else
-                   range_list_materialize(li->li_tv.vval.v_list);
+                   CHECK_LIST_MATERIALIZE(li->li_tv.vval.v_list);
            }
        }
        if (ok)
index 6c047f332d0c0754bf18e4de8202a411b0335676..592c7d19fd445dd151499c2442585f276712c82b 100644 (file)
@@ -59,6 +59,7 @@ void ga_clear_strings(garray_T *gap);
 void ga_init(garray_T *gap);
 void ga_init2(garray_T *gap, int itemsize, int growsize);
 int ga_grow(garray_T *gap, int n);
+int ga_grow_inner(garray_T *gap, int n);
 char_u *ga_concat_strings(garray_T *gap, char *sep);
 void ga_add_string(garray_T *gap, char_u *p);
 void ga_concat(garray_T *gap, char_u *s);
index b33aee77410fa6efe0c6b53115e194dbf8ba7ee2..5a64ccb75ffe2b3b6fc53d6a765d1a505f92e569 100644 (file)
@@ -1718,7 +1718,7 @@ func_call(
     int                argc = 0;
     int                r = 0;
 
-    range_list_materialize(l);
+    CHECK_LIST_MATERIALIZE(l);
     FOR_ALL_LIST_ITEMS(l, item)
     {
        if (argc == MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc))