diff src/list.c @ 30566:b3de17181c19 v9.0.0618

patch 9.0.0618: calling function for reduce() has too much overhead Commit: https://github.com/vim/vim/commit/82418263fa91792e851cb0de879d1595327d5531 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Sep 28 16:16:15 2022 +0100 patch 9.0.0618: calling function for reduce() has too much overhead Problem: Calling function for reduce() has too much overhead. Solution: Do not create a funccall_T every time.
author Bram Moolenaar <Bram@vim.org>
date Wed, 28 Sep 2022 17:30:04 +0200
parents 30025bbc1705
children b1c66bff0a66
line wrap: on
line diff
--- a/src/list.c
+++ b/src/list.c
@@ -2320,6 +2320,7 @@ filter_map_one(
 	typval_T	*tv,	    // original value
 	typval_T	*expr,	    // callback
 	filtermap_T	filtermap,
+	funccall_T	*fc,	    // from eval_expr_get_funccal()
 	typval_T	*newtv,	    // for map() and mapnew(): new value
 	int		*remp)	    // for filter(): remove flag
 {
@@ -2329,7 +2330,7 @@ filter_map_one(
     copy_tv(tv, get_vim_var_tv(VV_VAL));
     argv[0] = *get_vim_var_tv(VV_KEY);
     argv[1] = *get_vim_var_tv(VV_VAL);
-    if (eval_expr_typval(expr, argv, 2, newtv) == FAIL)
+    if (eval_expr_typval(expr, argv, 2, fc, newtv) == FAIL)
 	goto theend;
     if (filtermap == FILTERMAP_FILTER)
     {
@@ -2371,6 +2372,8 @@ list_filter_map(
     int		idx = 0;
     int		rem;
     listitem_T	*li, *nli;
+    typval_T	newtv;
+    funccall_T	*fc;
 
     if (filtermap == FILTERMAP_MAPNEW)
     {
@@ -2395,6 +2398,9 @@ list_filter_map(
     if (filtermap != FILTERMAP_FILTER && l->lv_lock == 0)
 	l->lv_lock = VAR_LOCKED;
 
+    // Create one funccal_T for all eval_expr_typval() calls.
+    fc = eval_expr_get_funccal(expr, &newtv);
+
     if (l->lv_first == &range_list_item)
     {
 	varnumber_T	val = l->lv_u.nonmat.lv_start;
@@ -2413,13 +2419,12 @@ list_filter_map(
 	for (idx = 0; idx < len; ++idx)
 	{
 	    typval_T tv;
-	    typval_T newtv;
 
 	    tv.v_type = VAR_NUMBER;
 	    tv.v_lock = 0;
 	    tv.vval.v_number = val;
 	    set_vim_var_nr(VV_KEY, idx);
-	    if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL)
+	    if (filter_map_one(&tv, expr, filtermap, fc, &newtv, &rem) == FAIL)
 		break;
 	    if (did_emsg)
 	    {
@@ -2457,15 +2462,13 @@ list_filter_map(
 	// Materialized list: loop over the items
 	for (li = l->lv_first; li != NULL; li = nli)
 	{
-	    typval_T newtv;
-
 	    if (filtermap == FILTERMAP_MAP && value_check_lock(
 			li->li_tv.v_lock, arg_errmsg, TRUE))
 		break;
 	    nli = li->li_next;
 	    set_vim_var_nr(VV_KEY, idx);
-	    if (filter_map_one(&li->li_tv, expr, filtermap,
-			&newtv, &rem) == FAIL)
+	    if (filter_map_one(&li->li_tv, expr, filtermap, fc,
+							 &newtv, &rem) == FAIL)
 		break;
 	    if (did_emsg)
 	    {
@@ -2498,6 +2501,8 @@ list_filter_map(
     }
 
     l->lv_lock = prev_lock;
+    if (fc != NULL)
+	remove_funccal();
 }
 
 /*
@@ -3018,6 +3023,7 @@ list_reduce(
     int		r;
     int		called_emsg_start = called_emsg;
     int		prev_locked;
+    funccall_T	*fc;
 
     // Using reduce on a range() uses "range_idx" and "range_val".
     range_list = l != NULL && l->lv_first == &range_list_item;
@@ -3055,6 +3061,9 @@ list_reduce(
     if (l == NULL)
 	return;
 
+    // Create one funccal_T for all eval_expr_typval() calls.
+    fc = eval_expr_get_funccal(expr, rettv);
+
     prev_locked = l->lv_lock;
     l->lv_lock = VAR_FIXED;  // disallow the list changing here
 
@@ -3071,7 +3080,7 @@ list_reduce(
 	else
 	    argv[1] = li->li_tv;
 
-	r = eval_expr_typval(expr, argv, 2, rettv);
+	r = eval_expr_typval(expr, argv, 2, fc, rettv);
 
 	if (argv[0].v_type != VAR_NUMBER && argv[0].v_type != VAR_UNKNOWN)
 	    clear_tv(&argv[0]);
@@ -3088,6 +3097,9 @@ list_reduce(
 	    li = li->li_next;
     }
 
+    if (fc != NULL)
+	remove_funccal();
+
     l->lv_lock = prev_locked;
 }