Mercurial > vim
comparison 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 |
comparison
equal
deleted
inserted
replaced
30565:ce8e4c9cc95a | 30566:b3de17181c19 |
---|---|
2318 int | 2318 int |
2319 filter_map_one( | 2319 filter_map_one( |
2320 typval_T *tv, // original value | 2320 typval_T *tv, // original value |
2321 typval_T *expr, // callback | 2321 typval_T *expr, // callback |
2322 filtermap_T filtermap, | 2322 filtermap_T filtermap, |
2323 funccall_T *fc, // from eval_expr_get_funccal() | |
2323 typval_T *newtv, // for map() and mapnew(): new value | 2324 typval_T *newtv, // for map() and mapnew(): new value |
2324 int *remp) // for filter(): remove flag | 2325 int *remp) // for filter(): remove flag |
2325 { | 2326 { |
2326 typval_T argv[3]; | 2327 typval_T argv[3]; |
2327 int retval = FAIL; | 2328 int retval = FAIL; |
2328 | 2329 |
2329 copy_tv(tv, get_vim_var_tv(VV_VAL)); | 2330 copy_tv(tv, get_vim_var_tv(VV_VAL)); |
2330 argv[0] = *get_vim_var_tv(VV_KEY); | 2331 argv[0] = *get_vim_var_tv(VV_KEY); |
2331 argv[1] = *get_vim_var_tv(VV_VAL); | 2332 argv[1] = *get_vim_var_tv(VV_VAL); |
2332 if (eval_expr_typval(expr, argv, 2, newtv) == FAIL) | 2333 if (eval_expr_typval(expr, argv, 2, fc, newtv) == FAIL) |
2333 goto theend; | 2334 goto theend; |
2334 if (filtermap == FILTERMAP_FILTER) | 2335 if (filtermap == FILTERMAP_FILTER) |
2335 { | 2336 { |
2336 int error = FALSE; | 2337 int error = FALSE; |
2337 | 2338 |
2369 int prev_lock; | 2370 int prev_lock; |
2370 list_T *l_ret = NULL; | 2371 list_T *l_ret = NULL; |
2371 int idx = 0; | 2372 int idx = 0; |
2372 int rem; | 2373 int rem; |
2373 listitem_T *li, *nli; | 2374 listitem_T *li, *nli; |
2375 typval_T newtv; | |
2376 funccall_T *fc; | |
2374 | 2377 |
2375 if (filtermap == FILTERMAP_MAPNEW) | 2378 if (filtermap == FILTERMAP_MAPNEW) |
2376 { | 2379 { |
2377 rettv->v_type = VAR_LIST; | 2380 rettv->v_type = VAR_LIST; |
2378 rettv->vval.v_list = NULL; | 2381 rettv->vval.v_list = NULL; |
2392 // set_vim_var_nr() doesn't set the type | 2395 // set_vim_var_nr() doesn't set the type |
2393 set_vim_var_type(VV_KEY, VAR_NUMBER); | 2396 set_vim_var_type(VV_KEY, VAR_NUMBER); |
2394 | 2397 |
2395 if (filtermap != FILTERMAP_FILTER && l->lv_lock == 0) | 2398 if (filtermap != FILTERMAP_FILTER && l->lv_lock == 0) |
2396 l->lv_lock = VAR_LOCKED; | 2399 l->lv_lock = VAR_LOCKED; |
2400 | |
2401 // Create one funccal_T for all eval_expr_typval() calls. | |
2402 fc = eval_expr_get_funccal(expr, &newtv); | |
2397 | 2403 |
2398 if (l->lv_first == &range_list_item) | 2404 if (l->lv_first == &range_list_item) |
2399 { | 2405 { |
2400 varnumber_T val = l->lv_u.nonmat.lv_start; | 2406 varnumber_T val = l->lv_u.nonmat.lv_start; |
2401 int len = l->lv_len; | 2407 int len = l->lv_len; |
2411 } | 2417 } |
2412 | 2418 |
2413 for (idx = 0; idx < len; ++idx) | 2419 for (idx = 0; idx < len; ++idx) |
2414 { | 2420 { |
2415 typval_T tv; | 2421 typval_T tv; |
2416 typval_T newtv; | |
2417 | 2422 |
2418 tv.v_type = VAR_NUMBER; | 2423 tv.v_type = VAR_NUMBER; |
2419 tv.v_lock = 0; | 2424 tv.v_lock = 0; |
2420 tv.vval.v_number = val; | 2425 tv.vval.v_number = val; |
2421 set_vim_var_nr(VV_KEY, idx); | 2426 set_vim_var_nr(VV_KEY, idx); |
2422 if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL) | 2427 if (filter_map_one(&tv, expr, filtermap, fc, &newtv, &rem) == FAIL) |
2423 break; | 2428 break; |
2424 if (did_emsg) | 2429 if (did_emsg) |
2425 { | 2430 { |
2426 clear_tv(&newtv); | 2431 clear_tv(&newtv); |
2427 break; | 2432 break; |
2455 else | 2460 else |
2456 { | 2461 { |
2457 // Materialized list: loop over the items | 2462 // Materialized list: loop over the items |
2458 for (li = l->lv_first; li != NULL; li = nli) | 2463 for (li = l->lv_first; li != NULL; li = nli) |
2459 { | 2464 { |
2460 typval_T newtv; | |
2461 | |
2462 if (filtermap == FILTERMAP_MAP && value_check_lock( | 2465 if (filtermap == FILTERMAP_MAP && value_check_lock( |
2463 li->li_tv.v_lock, arg_errmsg, TRUE)) | 2466 li->li_tv.v_lock, arg_errmsg, TRUE)) |
2464 break; | 2467 break; |
2465 nli = li->li_next; | 2468 nli = li->li_next; |
2466 set_vim_var_nr(VV_KEY, idx); | 2469 set_vim_var_nr(VV_KEY, idx); |
2467 if (filter_map_one(&li->li_tv, expr, filtermap, | 2470 if (filter_map_one(&li->li_tv, expr, filtermap, fc, |
2468 &newtv, &rem) == FAIL) | 2471 &newtv, &rem) == FAIL) |
2469 break; | 2472 break; |
2470 if (did_emsg) | 2473 if (did_emsg) |
2471 { | 2474 { |
2472 clear_tv(&newtv); | 2475 clear_tv(&newtv); |
2473 break; | 2476 break; |
2496 ++idx; | 2499 ++idx; |
2497 } | 2500 } |
2498 } | 2501 } |
2499 | 2502 |
2500 l->lv_lock = prev_lock; | 2503 l->lv_lock = prev_lock; |
2504 if (fc != NULL) | |
2505 remove_funccal(); | |
2501 } | 2506 } |
2502 | 2507 |
2503 /* | 2508 /* |
2504 * Implementation of map() and filter(). | 2509 * Implementation of map() and filter(). |
2505 */ | 2510 */ |
3016 typval_T initial; | 3021 typval_T initial; |
3017 typval_T argv[3]; | 3022 typval_T argv[3]; |
3018 int r; | 3023 int r; |
3019 int called_emsg_start = called_emsg; | 3024 int called_emsg_start = called_emsg; |
3020 int prev_locked; | 3025 int prev_locked; |
3026 funccall_T *fc; | |
3021 | 3027 |
3022 // Using reduce on a range() uses "range_idx" and "range_val". | 3028 // Using reduce on a range() uses "range_idx" and "range_val". |
3023 range_list = l != NULL && l->lv_first == &range_list_item; | 3029 range_list = l != NULL && l->lv_first == &range_list_item; |
3024 if (range_list) | 3030 if (range_list) |
3025 range_val = l->lv_u.nonmat.lv_start; | 3031 range_val = l->lv_u.nonmat.lv_start; |
3053 copy_tv(&initial, rettv); | 3059 copy_tv(&initial, rettv); |
3054 | 3060 |
3055 if (l == NULL) | 3061 if (l == NULL) |
3056 return; | 3062 return; |
3057 | 3063 |
3064 // Create one funccal_T for all eval_expr_typval() calls. | |
3065 fc = eval_expr_get_funccal(expr, rettv); | |
3066 | |
3058 prev_locked = l->lv_lock; | 3067 prev_locked = l->lv_lock; |
3059 l->lv_lock = VAR_FIXED; // disallow the list changing here | 3068 l->lv_lock = VAR_FIXED; // disallow the list changing here |
3060 | 3069 |
3061 while (range_list ? range_idx < l->lv_len : li != NULL) | 3070 while (range_list ? range_idx < l->lv_len : li != NULL) |
3062 { | 3071 { |
3069 argv[1].vval.v_number = range_val; | 3078 argv[1].vval.v_number = range_val; |
3070 } | 3079 } |
3071 else | 3080 else |
3072 argv[1] = li->li_tv; | 3081 argv[1] = li->li_tv; |
3073 | 3082 |
3074 r = eval_expr_typval(expr, argv, 2, rettv); | 3083 r = eval_expr_typval(expr, argv, 2, fc, rettv); |
3075 | 3084 |
3076 if (argv[0].v_type != VAR_NUMBER && argv[0].v_type != VAR_UNKNOWN) | 3085 if (argv[0].v_type != VAR_NUMBER && argv[0].v_type != VAR_UNKNOWN) |
3077 clear_tv(&argv[0]); | 3086 clear_tv(&argv[0]); |
3078 if (r == FAIL || called_emsg != called_emsg_start) | 3087 if (r == FAIL || called_emsg != called_emsg_start) |
3079 break; | 3088 break; |
3086 } | 3095 } |
3087 else | 3096 else |
3088 li = li->li_next; | 3097 li = li->li_next; |
3089 } | 3098 } |
3090 | 3099 |
3100 if (fc != NULL) | |
3101 remove_funccal(); | |
3102 | |
3091 l->lv_lock = prev_locked; | 3103 l->lv_lock = prev_locked; |
3092 } | 3104 } |
3093 | 3105 |
3094 /* | 3106 /* |
3095 * "reduce(list, { accumulator, element -> value } [, initial])" function | 3107 * "reduce(list, { accumulator, element -> value } [, initial])" function |