Patch 8.2.3212

6 views
Skip to first unread message

Bram Moolenaar

unread,
Jul 24, 2021, 1:33:27 PM7/24/21
to vim...@googlegroups.com

Patch 8.2.3212
Problem: Vim9: execution speed can be improved.
Solution: Use __builtin_expect() to have the compiler produce better code.
(Dominique Pellé, closes #8613)
Files: src/vim9execute.c


*** ../vim-8.2.3211/src/vim9execute.c 2021-07-22 18:48:45.456351455 +0200
--- src/vim9execute.c 2021-07-24 19:30:12.080997318 +0200
***************
*** 22,27 ****
--- 22,35 ----

#include "vim9.h"

+ #if defined(__GNUC__) || defined(__clang__)
+ # define likely(x) __builtin_expect((x), 1)
+ # define unlikely(x) __builtin_expect((x), 0)
+ #else
+ # define unlikely(x) (x)
+ # define likely(x) (x)
+ #endif
+
// Structure put on ec_trystack when ISN_TRY is encountered.
typedef struct {
int tcd_frame_idx; // ec_frame_idx at ISN_TRY
***************
*** 137,143 ****

if (count > 0)
ectx->ec_stack.ga_len -= count - 1;
! else if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
return FAIL;
else
++ectx->ec_stack.ga_len;
--- 145,151 ----

if (count > 0)
ectx->ec_stack.ga_len -= count - 1;
! else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
return FAIL;
else
++ectx->ec_stack.ga_len;
***************
*** 210,216 ****
#ifdef FEAT_PROFILE
if (do_profiling == PROF_YES)
{
! if (ga_grow(&profile_info_ga, 1) == OK)
{
profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data)
+ profile_info_ga.ga_len;
--- 218,224 ----
#ifdef FEAT_PROFILE
if (do_profiling == PROF_YES)
{
! if (likely(ga_grow(&profile_info_ga, 1) == OK))
{
profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data)
+ profile_info_ga.ga_len;
***************
*** 289,296 ****
// - if needed: a counter for number of closures created in
// ectx->ec_funcrefs.
varcount = dfunc->df_varcount + dfunc->df_has_closure;
! if (ga_grow(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE + varcount)
! == FAIL)
return FAIL;

// If depth of calling is getting too high, don't execute the function.
--- 297,304 ----
// - if needed: a counter for number of closures created in
// ectx->ec_funcrefs.
varcount = dfunc->df_varcount + dfunc->df_has_closure;
! if (unlikely(ga_grow(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE
! + varcount) == FAIL))
return FAIL;

// If depth of calling is getting too high, don't execute the function.
***************
*** 361,367 ****
else
{
ref->or_outer = ALLOC_CLEAR_ONE(outer_T);
! if (ref->or_outer == NULL)
{
vim_free(ref);
return FAIL;
--- 369,375 ----
else
{
ref->or_outer = ALLOC_CLEAR_ONE(outer_T);
! if (unlikely(ref->or_outer == NULL))
{
vim_free(ref);
return FAIL;
***************
*** 703,709 ****
// Result replaces the arguments on the stack.
if (argcount > 0)
ectx->ec_stack.ga_len -= argcount - 1;
! else if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
return FAIL;
else
++ectx->ec_stack.ga_len;
--- 711,717 ----
// Result replaces the arguments on the stack.
if (argcount > 0)
ectx->ec_stack.ga_len -= argcount - 1;
! else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
return FAIL;
else
++ectx->ec_stack.ga_len;
***************
*** 941,947 ****
{
// Make space for arguments from the partial, shift the "argcount"
// arguments up.
! if (ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL)
return FAIL;
for (i = 1; i <= argcount; ++i)
*STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i);
--- 949,955 ----
{
// Make space for arguments from the partial, shift the "argcount"
// arguments up.
! if (unlikely(ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL))
return FAIL;
for (i = 1; i <= argcount; ++i)
*STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i);
***************
*** 1371,1377 ****
// If this function returns and the closure is still being used, we
// need to make a copy of the context (arguments and local variables).
// Store a reference to the partial so we can handle that.
! if (ga_grow(&ectx->ec_funcrefs, 1) == FAIL)
{
vim_free(pt);
return FAIL;
--- 1379,1385 ----
// If this function returns and the closure is still being used, we
// need to make a copy of the context (arguments and local variables).
// Store a reference to the partial so we can handle that.
! if (unlikely(ga_grow(&ectx->ec_funcrefs, 1) == FAIL))
{
vim_free(pt);
return FAIL;
***************
*** 1504,1510 ****
p = skipwhite(p);
if (*p == '#')
break;
! if (ga_grow(&ga, 1) == OK)
((char_u **)(ga.ga_data))[ga.ga_len++] = p;
if (STRNCMP(p, "def ", 4) == 0)
break;
--- 1512,1518 ----
p = skipwhite(p);
if (*p == '#')
break;
! if (likely(ga_grow(&ga, 1) == OK))
((char_u **)(ga.ga_data))[ga.ga_len++] = p;
if (STRNCMP(p, "def ", 4) == 0)
break;
***************
*** 1544,1555 ****
isn_T *iptr;
typval_T *tv;

! if (++breakcheck_count >= 100)
{
line_breakcheck();
breakcheck_count = 0;
}
! if (got_int)
{
// Turn CTRL-C into an exception.
got_int = FALSE;
--- 1552,1563 ----
isn_T *iptr;
typval_T *tv;

! if (unlikely(++breakcheck_count >= 100))
{
line_breakcheck();
breakcheck_count = 0;
}
! if (unlikely(got_int))
{
// Turn CTRL-C into an exception.
got_int = FALSE;
***************
*** 1558,1564 ****
did_throw = TRUE;
}

! if (did_emsg && msg_list != NULL && *msg_list != NULL)
{
// Turn an error message into an exception.
did_emsg = FALSE;
--- 1566,1572 ----
did_throw = TRUE;
}

! if (unlikely(did_emsg && msg_list != NULL && *msg_list != NULL))
{
// Turn an error message into an exception.
did_emsg = FALSE;
***************
*** 1568,1574 ****
*msg_list = NULL;
}

! if (did_throw)
{
garray_T *trystack = &ectx->ec_trystack;
trycmd_T *trycmd = NULL;
--- 1576,1582 ----
*msg_list = NULL;
}

! if (unlikely(did_throw))
{
garray_T *trystack = &ectx->ec_trystack;
trycmd_T *trycmd = NULL;
***************
*** 1605,1611 ****
{
// Not inside try or need to return from current functions.
// Push a dummy return value.
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_NUMBER;
--- 1613,1619 ----
{
// Not inside try or need to return from current functions.
// Push a dummy return value.
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_NUMBER;
***************
*** 1680,1686 ****
int res;
int save_flags = cmdmod.cmod_flags;

! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
init_tv(tv);
--- 1688,1694 ----
int res;
int save_flags = cmdmod.cmod_flags;

! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
tv = STACK_TV_BOT(0);
init_tv(tv);
***************
*** 1696,1702 ****
// push typeval VAR_INSTR with instructions to be executed
case ISN_INSTR:
{
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
tv->vval.v_instr = ALLOC_ONE(instr_T);
--- 1704,1710 ----
// push typeval VAR_INSTR with instructions to be executed
case ISN_INSTR:
{
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
tv = STACK_TV_BOT(0);
tv->vval.v_instr = ALLOC_ONE(instr_T);
***************
*** 1761,1767 ****
clear_redir_lval();
redir_vname = 0;

! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
{
vim_free(res);
goto theend;
--- 1769,1775 ----
clear_redir_lval();
redir_vname = 0;

! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
{
vim_free(res);
goto theend;
***************
*** 1828,1834 ****
if (pass == 1)
{
cmd = alloc(len + 1);
! if (cmd == NULL)
goto theend;
len = 0;
}
--- 1836,1842 ----
if (pass == 1)
{
cmd = alloc(len + 1);
! if (unlikely(cmd == NULL))
goto theend;
len = 0;
}
***************
*** 1897,1903 ****
p = tv_stringify(tv, buf);

len = (int)STRLEN(p);
! if (ga_grow(&ga, len + 2) == FAIL)
failed = TRUE;
else
{
--- 1905,1911 ----
p = tv_stringify(tv, buf);

len = (int)STRLEN(p);
! if (unlikely(ga_grow(&ga, len + 2) == FAIL))
failed = TRUE;
else
{
***************
*** 1948,1954 ****

// load local variable or argument
case ISN_LOAD:
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
--- 1956,1962 ----

// load local variable or argument
case ISN_LOAD:
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
***************
*** 1956,1962 ****

// load v: variable
case ISN_LOADV:
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
--- 1964,1970 ----

// load v: variable
case ISN_LOADV:
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
***************
*** 1972,1978 ****
if (sv == NULL)
goto theend;
allocate_if_null(sv->sv_tv);
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
copy_tv(sv->sv_tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
--- 1980,1986 ----
if (sv == NULL)
goto theend;
allocate_if_null(sv->sv_tv);
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
copy_tv(sv->sv_tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
***************
*** 1995,2001 ****
}
else
{
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
copy_tv(&di->di_tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
--- 2003,2009 ----
}
else
{
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
copy_tv(&di->di_tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
***************
*** 2045,2051 ****
}
else
{
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
copy_tv(&di->di_tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
--- 2053,2059 ----
}
else
{
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
copy_tv(&di->di_tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
***************
*** 2058,2064 ****
{
char_u *name = iptr->isn_arg.string;

! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
SOURCING_LNUM = iptr->isn_lnum;
if (eval_variable(name, (int)STRLEN(name),
--- 2066,2072 ----
{
char_u *name = iptr->isn_arg.string;

! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
SOURCING_LNUM = iptr->isn_lnum;
if (eval_variable(name, (int)STRLEN(name),
***************
*** 2085,2091 ****
default: // Cannot reach here
goto theend;
}
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_DICT;
--- 2093,2099 ----
default: // Cannot reach here
goto theend;
}
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_DICT;
***************
*** 2104,2110 ****

// This is not expected to fail, name is checked during
// compilation: don't set SOURCING_LNUM.
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
if (eval_option(&name, &optval, TRUE) == FAIL)
goto theend;
--- 2112,2118 ----

// This is not expected to fail, name is checked during
// compilation: don't set SOURCING_LNUM.
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
if (eval_option(&name, &optval, TRUE) == FAIL)
goto theend;
***************
*** 2119,2125 ****
typval_T optval;
char_u *name = iptr->isn_arg.string;

! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
// name is always valid, checked when compiling
(void)eval_env_var(&name, &optval, TRUE);
--- 2127,2133 ----
typval_T optval;
char_u *name = iptr->isn_arg.string;

! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
// name is always valid, checked when compiling
(void)eval_env_var(&name, &optval, TRUE);
***************
*** 2130,2136 ****

// load @register
case ISN_LOADREG:
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_STRING;
--- 2138,2144 ----

// load @register
case ISN_LOADREG:
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_STRING;
***************
*** 2565,2571 ****
+ iptr->isn_arg.outer.outer_idx;
if (iptr->isn_type == ISN_LOADOUTER)
{
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
copy_tv(tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
--- 2573,2579 ----
+ iptr->isn_arg.outer.outer_idx;
if (iptr->isn_type == ISN_LOADOUTER)
{
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
copy_tv(tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
***************
*** 2753,2759 ****
case ISN_PUSHFUNC:
case ISN_PUSHCHANNEL:
case ISN_PUSHJOB:
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
tv->v_lock = 0;
--- 2761,2767 ----
case ISN_PUSHFUNC:
case ISN_PUSHCHANNEL:
case ISN_PUSHJOB:
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
tv = STACK_TV_BOT(0);
tv->v_lock = 0;
***************
*** 2842,2848 ****
char_u *key;
int idx;

! if (dict == NULL)
goto theend;
for (idx = 0; idx < count; ++idx)
{
--- 2850,2856 ----
char_u *key;
int idx;

! if (unlikely(dict == NULL))
goto theend;
for (idx = 0; idx < count; ++idx)
{
***************
*** 2861,2867 ****
}
item = dictitem_alloc(key);
clear_tv(tv);
! if (item == NULL)
{
dict_unref(dict);
goto theend;
--- 2869,2875 ----
}
item = dictitem_alloc(key);
clear_tv(tv);
! if (unlikely(item == NULL))
{
dict_unref(dict);
goto theend;
***************
*** 2878,2884 ****

if (count > 0)
ectx->ec_stack.ga_len -= 2 * count - 1;
! else if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
else
++ectx->ec_stack.ga_len;
--- 2886,2892 ----

if (count > 0)
ectx->ec_stack.ga_len -= 2 * count - 1;
! else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
else
++ectx->ec_stack.ga_len;
***************
*** 2960,2966 ****

// return from a :def function call without a value
case ISN_RETURN_VOID:
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
++ectx->ec_stack.ga_len;
--- 2968,2974 ----

// return from a :def function call without a value
case ISN_RETURN_VOID:
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
tv = STACK_TV_BOT(0);
++ectx->ec_stack.ga_len;
***************
*** 3002,3008 ****

if (pt == NULL)
goto theend;
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
{
vim_free(pt);
goto theend;
--- 3010,3016 ----

if (pt == NULL)
goto theend;
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
{
vim_free(pt);
goto theend;
***************
*** 3097,3103 ****
typval_T *idxtv =
STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);

! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
if (ltv->v_type == VAR_LIST)
{
--- 3105,3111 ----
typval_T *idxtv =
STACK_TV_VAR(iptr->isn_arg.forloop.for_idx);

! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
if (ltv->v_type == VAR_LIST)
{
***************
*** 3204,3210 ****
{
trycmd_T *trycmd = NULL;

! if (GA_GROW(&ectx->ec_trystack, 1) == FAIL)
goto theend;
trycmd = ((trycmd_T *)ectx->ec_trystack.ga_data)
+ ectx->ec_trystack.ga_len;
--- 3212,3218 ----
{
trycmd_T *trycmd = NULL;

! if (unlikely(GA_GROW(&ectx->ec_trystack, 1) == FAIL))
goto theend;
trycmd = ((trycmd_T *)ectx->ec_trystack.ga_data)
+ ectx->ec_trystack.ga_len;
***************
*** 3229,3235 ****
iemsg("Evaluating catch while current_exception is NULL");
goto theend;
}
! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
tv = STACK_TV_BOT(0);
++ectx->ec_stack.ga_len;
--- 3237,3243 ----
iemsg("Evaluating catch while current_exception is NULL");
goto theend;
}
! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
tv = STACK_TV_BOT(0);
++ectx->ec_stack.ga_len;
***************
*** 3888,3894 ****
tv = STACK_TV_BOT(-1 - gi->gi_with_op);
li = list_find(tv->vval.v_list, gi->gi_index);

! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
++ectx->ec_stack.ga_len;
copy_tv(&li->li_tv, STACK_TV_BOT(-1));
--- 3896,3902 ----
tv = STACK_TV_BOT(-1 - gi->gi_with_op);
li = list_find(tv->vval.v_list, gi->gi_index);

! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
++ectx->ec_stack.ga_len;
copy_tv(&li->li_tv, STACK_TV_BOT(-1));
***************
*** 4123,4129 ****
if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
goto on_error;

! if (GA_GROW(&ectx->ec_stack, 1) == FAIL)
goto theend;
++ectx->ec_stack.ga_len;
tv = STACK_TV_BOT(-1);
--- 4131,4137 ----
if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL)
goto on_error;

! if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL))
goto theend;
++ectx->ec_stack.ga_len;
tv = STACK_TV_BOT(-1);
***************
*** 4225,4231 ****
}

CHECK_LIST_MATERIALIZE(l);
! if (GA_GROW(&ectx->ec_stack, count - 1) == FAIL)
goto theend;
ectx->ec_stack.ga_len += count - 1;

--- 4233,4239 ----
}

CHECK_LIST_MATERIALIZE(l);
! if (unlikely(GA_GROW(&ectx->ec_stack, count - 1) == FAIL))
goto theend;
ectx->ec_stack.ga_len += count - 1;

***************
*** 4499,4505 ****
CLEAR_FIELD(ectx);
ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
! if (ga_grow(&ectx.ec_stack, 20) == FAIL)
{
funcdepth_decrement();
return FAIL;
--- 4507,4513 ----
CLEAR_FIELD(ectx);
ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx;
ga_init2(&ectx.ec_stack, sizeof(typval_T), 500);
! if (unlikely(ga_grow(&ectx.ec_stack, 20) == FAIL))
{
funcdepth_decrement();
return FAIL;
***************
*** 5506,5512 ****
NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);

buf = alloc(len + 1);
! if (buf != NULL)
{
(void)produce_cmdmods(
buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
--- 5514,5520 ----
NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);

buf = alloc(len + 1);
! if (likely(buf != NULL))
{
(void)produce_cmdmods(
buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE);
*** ../vim-8.2.3211/src/version.c 2021-07-24 16:16:11.542239515 +0200
--- src/version.c 2021-07-24 19:30:35.532944023 +0200
***************
*** 757,758 ****
--- 757,760 ----
{ /* Add new patch number below this line */
+ /**/
+ 3212,
/**/

--
hundred-and-one symptoms of being an internet addict:
204. You have learned not to fall asleep on your keyboard
the hard way

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages