Mercurial > vim
comparison src/vim9execute.c @ 25350:0c5b84c5862a v8.2.3212
patch 8.2.3212: Vim9: execution speed can be improved
Commit: https://github.com/vim/vim/commit/5a9e5845e1539592e94963fcdf5b3ad4fdc59db4
Author: Dominique Pelle <dominique.pelle@gmail.com>
Date: Sat Jul 24 19:32:12 2021 +0200
patch 8.2.3212: Vim9: execution speed can be improved
Problem: Vim9: execution speed can be improved.
Solution: Use __builtin_expect() to have the compiler produce better code.
(Dominique Pell?, closes #8613)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 24 Jul 2021 19:45:04 +0200 |
parents | 820395d1137b |
children | effe5f2b4d01 |
comparison
equal
deleted
inserted
replaced
25349:d631e1a737d2 | 25350:0c5b84c5862a |
---|---|
19 #ifdef VMS | 19 #ifdef VMS |
20 # include <float.h> | 20 # include <float.h> |
21 #endif | 21 #endif |
22 | 22 |
23 #include "vim9.h" | 23 #include "vim9.h" |
24 | |
25 #if defined(__GNUC__) || defined(__clang__) | |
26 # define likely(x) __builtin_expect((x), 1) | |
27 # define unlikely(x) __builtin_expect((x), 0) | |
28 #else | |
29 # define unlikely(x) (x) | |
30 # define likely(x) (x) | |
31 #endif | |
24 | 32 |
25 // Structure put on ec_trystack when ISN_TRY is encountered. | 33 // Structure put on ec_trystack when ISN_TRY is encountered. |
26 typedef struct { | 34 typedef struct { |
27 int tcd_frame_idx; // ec_frame_idx at ISN_TRY | 35 int tcd_frame_idx; // ec_frame_idx at ISN_TRY |
28 int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY | 36 int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY |
135 for (idx = 0; idx < count; ++idx) | 143 for (idx = 0; idx < count; ++idx) |
136 list_set_item(list, idx, STACK_TV_BOT(idx - count)); | 144 list_set_item(list, idx, STACK_TV_BOT(idx - count)); |
137 | 145 |
138 if (count > 0) | 146 if (count > 0) |
139 ectx->ec_stack.ga_len -= count - 1; | 147 ectx->ec_stack.ga_len -= count - 1; |
140 else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 148 else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
141 return FAIL; | 149 return FAIL; |
142 else | 150 else |
143 ++ectx->ec_stack.ga_len; | 151 ++ectx->ec_stack.ga_len; |
144 tv = STACK_TV_BOT(-1); | 152 tv = STACK_TV_BOT(-1); |
145 tv->v_type = VAR_LIST; | 153 tv->v_type = VAR_LIST; |
208 } | 216 } |
209 | 217 |
210 #ifdef FEAT_PROFILE | 218 #ifdef FEAT_PROFILE |
211 if (do_profiling == PROF_YES) | 219 if (do_profiling == PROF_YES) |
212 { | 220 { |
213 if (ga_grow(&profile_info_ga, 1) == OK) | 221 if (likely(ga_grow(&profile_info_ga, 1) == OK)) |
214 { | 222 { |
215 profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data) | 223 profinfo_T *info = ((profinfo_T *)profile_info_ga.ga_data) |
216 + profile_info_ga.ga_len; | 224 + profile_info_ga.ga_len; |
217 ++profile_info_ga.ga_len; | 225 ++profile_info_ga.ga_len; |
218 CLEAR_POINTER(info); | 226 CLEAR_POINTER(info); |
287 // - stack frame | 295 // - stack frame |
288 // - local variables | 296 // - local variables |
289 // - if needed: a counter for number of closures created in | 297 // - if needed: a counter for number of closures created in |
290 // ectx->ec_funcrefs. | 298 // ectx->ec_funcrefs. |
291 varcount = dfunc->df_varcount + dfunc->df_has_closure; | 299 varcount = dfunc->df_varcount + dfunc->df_has_closure; |
292 if (ga_grow(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE + varcount) | 300 if (unlikely(ga_grow(&ectx->ec_stack, arg_to_add + STACK_FRAME_SIZE |
293 == FAIL) | 301 + varcount) == FAIL)) |
294 return FAIL; | 302 return FAIL; |
295 | 303 |
296 // If depth of calling is getting too high, don't execute the function. | 304 // If depth of calling is getting too high, don't execute the function. |
297 if (funcdepth_increment() == FAIL) | 305 if (funcdepth_increment() == FAIL) |
298 return FAIL; | 306 return FAIL; |
359 ref->or_partial = ufunc->uf_partial; | 367 ref->or_partial = ufunc->uf_partial; |
360 } | 368 } |
361 else | 369 else |
362 { | 370 { |
363 ref->or_outer = ALLOC_CLEAR_ONE(outer_T); | 371 ref->or_outer = ALLOC_CLEAR_ONE(outer_T); |
364 if (ref->or_outer == NULL) | 372 if (unlikely(ref->or_outer == NULL)) |
365 { | 373 { |
366 vim_free(ref); | 374 vim_free(ref); |
367 return FAIL; | 375 return FAIL; |
368 } | 376 } |
369 ref->or_outer_allocated = TRUE; | 377 ref->or_outer_allocated = TRUE; |
701 argvars[argcount].v_type = VAR_UNKNOWN; | 709 argvars[argcount].v_type = VAR_UNKNOWN; |
702 | 710 |
703 // Result replaces the arguments on the stack. | 711 // Result replaces the arguments on the stack. |
704 if (argcount > 0) | 712 if (argcount > 0) |
705 ectx->ec_stack.ga_len -= argcount - 1; | 713 ectx->ec_stack.ga_len -= argcount - 1; |
706 else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 714 else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
707 return FAIL; | 715 return FAIL; |
708 else | 716 else |
709 ++ectx->ec_stack.ga_len; | 717 ++ectx->ec_stack.ga_len; |
710 | 718 |
711 // Default return value is zero. | 719 // Default return value is zero. |
939 | 947 |
940 if (pt->pt_argc > 0) | 948 if (pt->pt_argc > 0) |
941 { | 949 { |
942 // Make space for arguments from the partial, shift the "argcount" | 950 // Make space for arguments from the partial, shift the "argcount" |
943 // arguments up. | 951 // arguments up. |
944 if (ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL) | 952 if (unlikely(ga_grow(&ectx->ec_stack, pt->pt_argc) == FAIL)) |
945 return FAIL; | 953 return FAIL; |
946 for (i = 1; i <= argcount; ++i) | 954 for (i = 1; i <= argcount; ++i) |
947 *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i); | 955 *STACK_TV_BOT(-i + pt->pt_argc) = *STACK_TV_BOT(-i); |
948 ectx->ec_stack.ga_len += pt->pt_argc; | 956 ectx->ec_stack.ga_len += pt->pt_argc; |
949 argcount += pt->pt_argc; | 957 argcount += pt->pt_argc; |
1369 } | 1377 } |
1370 | 1378 |
1371 // If this function returns and the closure is still being used, we | 1379 // If this function returns and the closure is still being used, we |
1372 // need to make a copy of the context (arguments and local variables). | 1380 // need to make a copy of the context (arguments and local variables). |
1373 // Store a reference to the partial so we can handle that. | 1381 // Store a reference to the partial so we can handle that. |
1374 if (ga_grow(&ectx->ec_funcrefs, 1) == FAIL) | 1382 if (unlikely(ga_grow(&ectx->ec_funcrefs, 1) == FAIL)) |
1375 { | 1383 { |
1376 vim_free(pt); | 1384 vim_free(pt); |
1377 return FAIL; | 1385 return FAIL; |
1378 } | 1386 } |
1379 // Extra variable keeps the count of closures created in the current | 1387 // Extra variable keeps the count of closures created in the current |
1502 if (p == NULL) | 1510 if (p == NULL) |
1503 continue; // left over from continuation line | 1511 continue; // left over from continuation line |
1504 p = skipwhite(p); | 1512 p = skipwhite(p); |
1505 if (*p == '#') | 1513 if (*p == '#') |
1506 break; | 1514 break; |
1507 if (ga_grow(&ga, 1) == OK) | 1515 if (likely(ga_grow(&ga, 1) == OK)) |
1508 ((char_u **)(ga.ga_data))[ga.ga_len++] = p; | 1516 ((char_u **)(ga.ga_data))[ga.ga_len++] = p; |
1509 if (STRNCMP(p, "def ", 4) == 0) | 1517 if (STRNCMP(p, "def ", 4) == 0) |
1510 break; | 1518 break; |
1511 } | 1519 } |
1512 line = ga_concat_strings(&ga, " "); | 1520 line = ga_concat_strings(&ga, " "); |
1542 { | 1550 { |
1543 static int breakcheck_count = 0; // using "static" makes it faster | 1551 static int breakcheck_count = 0; // using "static" makes it faster |
1544 isn_T *iptr; | 1552 isn_T *iptr; |
1545 typval_T *tv; | 1553 typval_T *tv; |
1546 | 1554 |
1547 if (++breakcheck_count >= 100) | 1555 if (unlikely(++breakcheck_count >= 100)) |
1548 { | 1556 { |
1549 line_breakcheck(); | 1557 line_breakcheck(); |
1550 breakcheck_count = 0; | 1558 breakcheck_count = 0; |
1551 } | 1559 } |
1552 if (got_int) | 1560 if (unlikely(got_int)) |
1553 { | 1561 { |
1554 // Turn CTRL-C into an exception. | 1562 // Turn CTRL-C into an exception. |
1555 got_int = FALSE; | 1563 got_int = FALSE; |
1556 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL) | 1564 if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL) |
1557 goto theend; | 1565 goto theend; |
1558 did_throw = TRUE; | 1566 did_throw = TRUE; |
1559 } | 1567 } |
1560 | 1568 |
1561 if (did_emsg && msg_list != NULL && *msg_list != NULL) | 1569 if (unlikely(did_emsg && msg_list != NULL && *msg_list != NULL)) |
1562 { | 1570 { |
1563 // Turn an error message into an exception. | 1571 // Turn an error message into an exception. |
1564 did_emsg = FALSE; | 1572 did_emsg = FALSE; |
1565 if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL) | 1573 if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL) |
1566 goto theend; | 1574 goto theend; |
1567 did_throw = TRUE; | 1575 did_throw = TRUE; |
1568 *msg_list = NULL; | 1576 *msg_list = NULL; |
1569 } | 1577 } |
1570 | 1578 |
1571 if (did_throw) | 1579 if (unlikely(did_throw)) |
1572 { | 1580 { |
1573 garray_T *trystack = &ectx->ec_trystack; | 1581 garray_T *trystack = &ectx->ec_trystack; |
1574 trycmd_T *trycmd = NULL; | 1582 trycmd_T *trycmd = NULL; |
1575 int index = trystack->ga_len; | 1583 int index = trystack->ga_len; |
1576 | 1584 |
1603 } | 1611 } |
1604 else | 1612 else |
1605 { | 1613 { |
1606 // Not inside try or need to return from current functions. | 1614 // Not inside try or need to return from current functions. |
1607 // Push a dummy return value. | 1615 // Push a dummy return value. |
1608 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 1616 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
1609 goto theend; | 1617 goto theend; |
1610 tv = STACK_TV_BOT(0); | 1618 tv = STACK_TV_BOT(0); |
1611 tv->v_type = VAR_NUMBER; | 1619 tv->v_type = VAR_NUMBER; |
1612 tv->vval.v_number = 0; | 1620 tv->vval.v_number = 0; |
1613 ++ectx->ec_stack.ga_len; | 1621 ++ectx->ec_stack.ga_len; |
1678 { | 1686 { |
1679 char_u *arg = iptr->isn_arg.string; | 1687 char_u *arg = iptr->isn_arg.string; |
1680 int res; | 1688 int res; |
1681 int save_flags = cmdmod.cmod_flags; | 1689 int save_flags = cmdmod.cmod_flags; |
1682 | 1690 |
1683 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 1691 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
1684 goto theend; | 1692 goto theend; |
1685 tv = STACK_TV_BOT(0); | 1693 tv = STACK_TV_BOT(0); |
1686 init_tv(tv); | 1694 init_tv(tv); |
1687 cmdmod.cmod_flags |= CMOD_LEGACY; | 1695 cmdmod.cmod_flags |= CMOD_LEGACY; |
1688 res = eval0(arg, tv, NULL, &EVALARG_EVALUATE); | 1696 res = eval0(arg, tv, NULL, &EVALARG_EVALUATE); |
1694 break; | 1702 break; |
1695 | 1703 |
1696 // push typeval VAR_INSTR with instructions to be executed | 1704 // push typeval VAR_INSTR with instructions to be executed |
1697 case ISN_INSTR: | 1705 case ISN_INSTR: |
1698 { | 1706 { |
1699 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 1707 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
1700 goto theend; | 1708 goto theend; |
1701 tv = STACK_TV_BOT(0); | 1709 tv = STACK_TV_BOT(0); |
1702 tv->vval.v_instr = ALLOC_ONE(instr_T); | 1710 tv->vval.v_instr = ALLOC_ONE(instr_T); |
1703 if (tv->vval.v_instr == NULL) | 1711 if (tv->vval.v_instr == NULL) |
1704 goto on_error; | 1712 goto on_error; |
1759 | 1767 |
1760 // End redirection, put redirected text on the stack. | 1768 // End redirection, put redirected text on the stack. |
1761 clear_redir_lval(); | 1769 clear_redir_lval(); |
1762 redir_vname = 0; | 1770 redir_vname = 0; |
1763 | 1771 |
1764 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 1772 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
1765 { | 1773 { |
1766 vim_free(res); | 1774 vim_free(res); |
1767 goto theend; | 1775 goto theend; |
1768 } | 1776 } |
1769 tv = STACK_TV_BOT(0); | 1777 tv = STACK_TV_BOT(0); |
1826 clear_tv(tv); | 1834 clear_tv(tv); |
1827 } | 1835 } |
1828 if (pass == 1) | 1836 if (pass == 1) |
1829 { | 1837 { |
1830 cmd = alloc(len + 1); | 1838 cmd = alloc(len + 1); |
1831 if (cmd == NULL) | 1839 if (unlikely(cmd == NULL)) |
1832 goto theend; | 1840 goto theend; |
1833 len = 0; | 1841 len = 0; |
1834 } | 1842 } |
1835 } | 1843 } |
1836 | 1844 |
1895 } | 1903 } |
1896 else | 1904 else |
1897 p = tv_stringify(tv, buf); | 1905 p = tv_stringify(tv, buf); |
1898 | 1906 |
1899 len = (int)STRLEN(p); | 1907 len = (int)STRLEN(p); |
1900 if (ga_grow(&ga, len + 2) == FAIL) | 1908 if (unlikely(ga_grow(&ga, len + 2) == FAIL)) |
1901 failed = TRUE; | 1909 failed = TRUE; |
1902 else | 1910 else |
1903 { | 1911 { |
1904 if (ga.ga_len > 0) | 1912 if (ga.ga_len > 0) |
1905 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; | 1913 ((char_u *)(ga.ga_data))[ga.ga_len++] = ' '; |
1946 } | 1954 } |
1947 break; | 1955 break; |
1948 | 1956 |
1949 // load local variable or argument | 1957 // load local variable or argument |
1950 case ISN_LOAD: | 1958 case ISN_LOAD: |
1951 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 1959 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
1952 goto theend; | 1960 goto theend; |
1953 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); | 1961 copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); |
1954 ++ectx->ec_stack.ga_len; | 1962 ++ectx->ec_stack.ga_len; |
1955 break; | 1963 break; |
1956 | 1964 |
1957 // load v: variable | 1965 // load v: variable |
1958 case ISN_LOADV: | 1966 case ISN_LOADV: |
1959 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 1967 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
1960 goto theend; | 1968 goto theend; |
1961 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0)); | 1969 copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0)); |
1962 ++ectx->ec_stack.ga_len; | 1970 ++ectx->ec_stack.ga_len; |
1963 break; | 1971 break; |
1964 | 1972 |
1970 | 1978 |
1971 sv = get_script_svar(sref, ectx); | 1979 sv = get_script_svar(sref, ectx); |
1972 if (sv == NULL) | 1980 if (sv == NULL) |
1973 goto theend; | 1981 goto theend; |
1974 allocate_if_null(sv->sv_tv); | 1982 allocate_if_null(sv->sv_tv); |
1975 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 1983 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
1976 goto theend; | 1984 goto theend; |
1977 copy_tv(sv->sv_tv, STACK_TV_BOT(0)); | 1985 copy_tv(sv->sv_tv, STACK_TV_BOT(0)); |
1978 ++ectx->ec_stack.ga_len; | 1986 ++ectx->ec_stack.ga_len; |
1979 } | 1987 } |
1980 break; | 1988 break; |
1993 semsg(_(e_undefined_variable_str), name); | 2001 semsg(_(e_undefined_variable_str), name); |
1994 goto on_error; | 2002 goto on_error; |
1995 } | 2003 } |
1996 else | 2004 else |
1997 { | 2005 { |
1998 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2006 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
1999 goto theend; | 2007 goto theend; |
2000 copy_tv(&di->di_tv, STACK_TV_BOT(0)); | 2008 copy_tv(&di->di_tv, STACK_TV_BOT(0)); |
2001 ++ectx->ec_stack.ga_len; | 2009 ++ectx->ec_stack.ga_len; |
2002 } | 2010 } |
2003 } | 2011 } |
2043 namespace, iptr->isn_arg.string); | 2051 namespace, iptr->isn_arg.string); |
2044 goto on_error; | 2052 goto on_error; |
2045 } | 2053 } |
2046 else | 2054 else |
2047 { | 2055 { |
2048 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2056 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2049 goto theend; | 2057 goto theend; |
2050 copy_tv(&di->di_tv, STACK_TV_BOT(0)); | 2058 copy_tv(&di->di_tv, STACK_TV_BOT(0)); |
2051 ++ectx->ec_stack.ga_len; | 2059 ++ectx->ec_stack.ga_len; |
2052 } | 2060 } |
2053 } | 2061 } |
2056 // load autoload variable | 2064 // load autoload variable |
2057 case ISN_LOADAUTO: | 2065 case ISN_LOADAUTO: |
2058 { | 2066 { |
2059 char_u *name = iptr->isn_arg.string; | 2067 char_u *name = iptr->isn_arg.string; |
2060 | 2068 |
2061 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2069 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2062 goto theend; | 2070 goto theend; |
2063 SOURCING_LNUM = iptr->isn_lnum; | 2071 SOURCING_LNUM = iptr->isn_lnum; |
2064 if (eval_variable(name, (int)STRLEN(name), | 2072 if (eval_variable(name, (int)STRLEN(name), |
2065 STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL) | 2073 STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL) |
2066 goto on_error; | 2074 goto on_error; |
2083 case ISN_LOADWDICT: d = curwin->w_vars; break; | 2091 case ISN_LOADWDICT: d = curwin->w_vars; break; |
2084 case ISN_LOADTDICT: d = curtab->tp_vars; break; | 2092 case ISN_LOADTDICT: d = curtab->tp_vars; break; |
2085 default: // Cannot reach here | 2093 default: // Cannot reach here |
2086 goto theend; | 2094 goto theend; |
2087 } | 2095 } |
2088 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2096 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2089 goto theend; | 2097 goto theend; |
2090 tv = STACK_TV_BOT(0); | 2098 tv = STACK_TV_BOT(0); |
2091 tv->v_type = VAR_DICT; | 2099 tv->v_type = VAR_DICT; |
2092 tv->v_lock = 0; | 2100 tv->v_lock = 0; |
2093 tv->vval.v_dict = d; | 2101 tv->vval.v_dict = d; |
2102 typval_T optval; | 2110 typval_T optval; |
2103 char_u *name = iptr->isn_arg.string; | 2111 char_u *name = iptr->isn_arg.string; |
2104 | 2112 |
2105 // This is not expected to fail, name is checked during | 2113 // This is not expected to fail, name is checked during |
2106 // compilation: don't set SOURCING_LNUM. | 2114 // compilation: don't set SOURCING_LNUM. |
2107 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2115 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2108 goto theend; | 2116 goto theend; |
2109 if (eval_option(&name, &optval, TRUE) == FAIL) | 2117 if (eval_option(&name, &optval, TRUE) == FAIL) |
2110 goto theend; | 2118 goto theend; |
2111 *STACK_TV_BOT(0) = optval; | 2119 *STACK_TV_BOT(0) = optval; |
2112 ++ectx->ec_stack.ga_len; | 2120 ++ectx->ec_stack.ga_len; |
2117 case ISN_LOADENV: | 2125 case ISN_LOADENV: |
2118 { | 2126 { |
2119 typval_T optval; | 2127 typval_T optval; |
2120 char_u *name = iptr->isn_arg.string; | 2128 char_u *name = iptr->isn_arg.string; |
2121 | 2129 |
2122 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2130 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2123 goto theend; | 2131 goto theend; |
2124 // name is always valid, checked when compiling | 2132 // name is always valid, checked when compiling |
2125 (void)eval_env_var(&name, &optval, TRUE); | 2133 (void)eval_env_var(&name, &optval, TRUE); |
2126 *STACK_TV_BOT(0) = optval; | 2134 *STACK_TV_BOT(0) = optval; |
2127 ++ectx->ec_stack.ga_len; | 2135 ++ectx->ec_stack.ga_len; |
2128 } | 2136 } |
2129 break; | 2137 break; |
2130 | 2138 |
2131 // load @register | 2139 // load @register |
2132 case ISN_LOADREG: | 2140 case ISN_LOADREG: |
2133 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2141 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2134 goto theend; | 2142 goto theend; |
2135 tv = STACK_TV_BOT(0); | 2143 tv = STACK_TV_BOT(0); |
2136 tv->v_type = VAR_STRING; | 2144 tv->v_type = VAR_STRING; |
2137 tv->v_lock = 0; | 2145 tv->v_lock = 0; |
2138 // This may result in NULL, which should be equivalent to an | 2146 // This may result in NULL, which should be equivalent to an |
2563 tv = ((typval_T *)outer->out_stack->ga_data) | 2571 tv = ((typval_T *)outer->out_stack->ga_data) |
2564 + outer->out_frame_idx + STACK_FRAME_SIZE | 2572 + outer->out_frame_idx + STACK_FRAME_SIZE |
2565 + iptr->isn_arg.outer.outer_idx; | 2573 + iptr->isn_arg.outer.outer_idx; |
2566 if (iptr->isn_type == ISN_LOADOUTER) | 2574 if (iptr->isn_type == ISN_LOADOUTER) |
2567 { | 2575 { |
2568 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2576 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2569 goto theend; | 2577 goto theend; |
2570 copy_tv(tv, STACK_TV_BOT(0)); | 2578 copy_tv(tv, STACK_TV_BOT(0)); |
2571 ++ectx->ec_stack.ga_len; | 2579 ++ectx->ec_stack.ga_len; |
2572 } | 2580 } |
2573 else | 2581 else |
2751 case ISN_PUSHS: | 2759 case ISN_PUSHS: |
2752 case ISN_PUSHBLOB: | 2760 case ISN_PUSHBLOB: |
2753 case ISN_PUSHFUNC: | 2761 case ISN_PUSHFUNC: |
2754 case ISN_PUSHCHANNEL: | 2762 case ISN_PUSHCHANNEL: |
2755 case ISN_PUSHJOB: | 2763 case ISN_PUSHJOB: |
2756 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2764 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2757 goto theend; | 2765 goto theend; |
2758 tv = STACK_TV_BOT(0); | 2766 tv = STACK_TV_BOT(0); |
2759 tv->v_lock = 0; | 2767 tv->v_lock = 0; |
2760 ++ectx->ec_stack.ga_len; | 2768 ++ectx->ec_stack.ga_len; |
2761 switch (iptr->isn_type) | 2769 switch (iptr->isn_type) |
2840 dict_T *dict = dict_alloc(); | 2848 dict_T *dict = dict_alloc(); |
2841 dictitem_T *item; | 2849 dictitem_T *item; |
2842 char_u *key; | 2850 char_u *key; |
2843 int idx; | 2851 int idx; |
2844 | 2852 |
2845 if (dict == NULL) | 2853 if (unlikely(dict == NULL)) |
2846 goto theend; | 2854 goto theend; |
2847 for (idx = 0; idx < count; ++idx) | 2855 for (idx = 0; idx < count; ++idx) |
2848 { | 2856 { |
2849 // have already checked key type is VAR_STRING | 2857 // have already checked key type is VAR_STRING |
2850 tv = STACK_TV_BOT(2 * (idx - count)); | 2858 tv = STACK_TV_BOT(2 * (idx - count)); |
2859 dict_unref(dict); | 2867 dict_unref(dict); |
2860 goto on_error; | 2868 goto on_error; |
2861 } | 2869 } |
2862 item = dictitem_alloc(key); | 2870 item = dictitem_alloc(key); |
2863 clear_tv(tv); | 2871 clear_tv(tv); |
2864 if (item == NULL) | 2872 if (unlikely(item == NULL)) |
2865 { | 2873 { |
2866 dict_unref(dict); | 2874 dict_unref(dict); |
2867 goto theend; | 2875 goto theend; |
2868 } | 2876 } |
2869 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); | 2877 item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); |
2876 } | 2884 } |
2877 } | 2885 } |
2878 | 2886 |
2879 if (count > 0) | 2887 if (count > 0) |
2880 ectx->ec_stack.ga_len -= 2 * count - 1; | 2888 ectx->ec_stack.ga_len -= 2 * count - 1; |
2881 else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2889 else if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2882 goto theend; | 2890 goto theend; |
2883 else | 2891 else |
2884 ++ectx->ec_stack.ga_len; | 2892 ++ectx->ec_stack.ga_len; |
2885 tv = STACK_TV_BOT(-1); | 2893 tv = STACK_TV_BOT(-1); |
2886 tv->v_type = VAR_DICT; | 2894 tv->v_type = VAR_DICT; |
2958 } | 2966 } |
2959 break; | 2967 break; |
2960 | 2968 |
2961 // return from a :def function call without a value | 2969 // return from a :def function call without a value |
2962 case ISN_RETURN_VOID: | 2970 case ISN_RETURN_VOID: |
2963 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 2971 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
2964 goto theend; | 2972 goto theend; |
2965 tv = STACK_TV_BOT(0); | 2973 tv = STACK_TV_BOT(0); |
2966 ++ectx->ec_stack.ga_len; | 2974 ++ectx->ec_stack.ga_len; |
2967 tv->v_type = VAR_VOID; | 2975 tv->v_type = VAR_VOID; |
2968 tv->vval.v_number = 0; | 2976 tv->vval.v_number = 0; |
3000 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data) | 3008 dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data) |
3001 + iptr->isn_arg.funcref.fr_func; | 3009 + iptr->isn_arg.funcref.fr_func; |
3002 | 3010 |
3003 if (pt == NULL) | 3011 if (pt == NULL) |
3004 goto theend; | 3012 goto theend; |
3005 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 3013 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
3006 { | 3014 { |
3007 vim_free(pt); | 3015 vim_free(pt); |
3008 goto theend; | 3016 goto theend; |
3009 } | 3017 } |
3010 if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc, | 3018 if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc, |
3095 { | 3103 { |
3096 typval_T *ltv = STACK_TV_BOT(-1); | 3104 typval_T *ltv = STACK_TV_BOT(-1); |
3097 typval_T *idxtv = | 3105 typval_T *idxtv = |
3098 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx); | 3106 STACK_TV_VAR(iptr->isn_arg.forloop.for_idx); |
3099 | 3107 |
3100 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 3108 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
3101 goto theend; | 3109 goto theend; |
3102 if (ltv->v_type == VAR_LIST) | 3110 if (ltv->v_type == VAR_LIST) |
3103 { | 3111 { |
3104 list_T *list = ltv->vval.v_list; | 3112 list_T *list = ltv->vval.v_list; |
3105 | 3113 |
3202 // start of ":try" block | 3210 // start of ":try" block |
3203 case ISN_TRY: | 3211 case ISN_TRY: |
3204 { | 3212 { |
3205 trycmd_T *trycmd = NULL; | 3213 trycmd_T *trycmd = NULL; |
3206 | 3214 |
3207 if (GA_GROW(&ectx->ec_trystack, 1) == FAIL) | 3215 if (unlikely(GA_GROW(&ectx->ec_trystack, 1) == FAIL)) |
3208 goto theend; | 3216 goto theend; |
3209 trycmd = ((trycmd_T *)ectx->ec_trystack.ga_data) | 3217 trycmd = ((trycmd_T *)ectx->ec_trystack.ga_data) |
3210 + ectx->ec_trystack.ga_len; | 3218 + ectx->ec_trystack.ga_len; |
3211 ++ectx->ec_trystack.ga_len; | 3219 ++ectx->ec_trystack.ga_len; |
3212 ++trylevel; | 3220 ++trylevel; |
3227 { | 3235 { |
3228 SOURCING_LNUM = iptr->isn_lnum; | 3236 SOURCING_LNUM = iptr->isn_lnum; |
3229 iemsg("Evaluating catch while current_exception is NULL"); | 3237 iemsg("Evaluating catch while current_exception is NULL"); |
3230 goto theend; | 3238 goto theend; |
3231 } | 3239 } |
3232 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 3240 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
3233 goto theend; | 3241 goto theend; |
3234 tv = STACK_TV_BOT(0); | 3242 tv = STACK_TV_BOT(0); |
3235 ++ectx->ec_stack.ga_len; | 3243 ++ectx->ec_stack.ga_len; |
3236 tv->v_type = VAR_STRING; | 3244 tv->v_type = VAR_STRING; |
3237 tv->v_lock = 0; | 3245 tv->v_lock = 0; |
3886 // Get list item: list is at stack-1, push item. | 3894 // Get list item: list is at stack-1, push item. |
3887 // List type and length is checked for when compiling. | 3895 // List type and length is checked for when compiling. |
3888 tv = STACK_TV_BOT(-1 - gi->gi_with_op); | 3896 tv = STACK_TV_BOT(-1 - gi->gi_with_op); |
3889 li = list_find(tv->vval.v_list, gi->gi_index); | 3897 li = list_find(tv->vval.v_list, gi->gi_index); |
3890 | 3898 |
3891 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 3899 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
3892 goto theend; | 3900 goto theend; |
3893 ++ectx->ec_stack.ga_len; | 3901 ++ectx->ec_stack.ga_len; |
3894 copy_tv(&li->li_tv, STACK_TV_BOT(-1)); | 3902 copy_tv(&li->li_tv, STACK_TV_BOT(-1)); |
3895 | 3903 |
3896 // Useful when used in unpack assignment. Reset at | 3904 // Useful when used in unpack assignment. Reset at |
4121 ea.cmd = iptr->isn_arg.string; | 4129 ea.cmd = iptr->isn_arg.string; |
4122 ea.skip = FALSE; | 4130 ea.skip = FALSE; |
4123 if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL) | 4131 if (parse_cmd_address(&ea, &errormsg, FALSE) == FAIL) |
4124 goto on_error; | 4132 goto on_error; |
4125 | 4133 |
4126 if (GA_GROW(&ectx->ec_stack, 1) == FAIL) | 4134 if (unlikely(GA_GROW(&ectx->ec_stack, 1) == FAIL)) |
4127 goto theend; | 4135 goto theend; |
4128 ++ectx->ec_stack.ga_len; | 4136 ++ectx->ec_stack.ga_len; |
4129 tv = STACK_TV_BOT(-1); | 4137 tv = STACK_TV_BOT(-1); |
4130 tv->v_type = VAR_NUMBER; | 4138 tv->v_type = VAR_NUMBER; |
4131 tv->v_lock = 0; | 4139 tv->v_lock = 0; |
4223 emsg(_(e_list_value_has_more_items_than_targets)); | 4231 emsg(_(e_list_value_has_more_items_than_targets)); |
4224 goto on_error; | 4232 goto on_error; |
4225 } | 4233 } |
4226 | 4234 |
4227 CHECK_LIST_MATERIALIZE(l); | 4235 CHECK_LIST_MATERIALIZE(l); |
4228 if (GA_GROW(&ectx->ec_stack, count - 1) == FAIL) | 4236 if (unlikely(GA_GROW(&ectx->ec_stack, count - 1) == FAIL)) |
4229 goto theend; | 4237 goto theend; |
4230 ectx->ec_stack.ga_len += count - 1; | 4238 ectx->ec_stack.ga_len += count - 1; |
4231 | 4239 |
4232 // Variable after semicolon gets a list with the remaining | 4240 // Variable after semicolon gets a list with the remaining |
4233 // items. | 4241 // items. |
4497 return FAIL; | 4505 return FAIL; |
4498 | 4506 |
4499 CLEAR_FIELD(ectx); | 4507 CLEAR_FIELD(ectx); |
4500 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; | 4508 ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; |
4501 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); | 4509 ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); |
4502 if (ga_grow(&ectx.ec_stack, 20) == FAIL) | 4510 if (unlikely(ga_grow(&ectx.ec_stack, 20) == FAIL)) |
4503 { | 4511 { |
4504 funcdepth_decrement(); | 4512 funcdepth_decrement(); |
4505 return FAIL; | 4513 return FAIL; |
4506 } | 4514 } |
4507 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); | 4515 ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); |
5504 char_u *buf; | 5512 char_u *buf; |
5505 size_t len = produce_cmdmods( | 5513 size_t len = produce_cmdmods( |
5506 NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE); | 5514 NULL, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE); |
5507 | 5515 |
5508 buf = alloc(len + 1); | 5516 buf = alloc(len + 1); |
5509 if (buf != NULL) | 5517 if (likely(buf != NULL)) |
5510 { | 5518 { |
5511 (void)produce_cmdmods( | 5519 (void)produce_cmdmods( |
5512 buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE); | 5520 buf, iptr->isn_arg.cmdmod.cf_cmdmod, FALSE); |
5513 smsg("%s%4d CMDMOD %s", pfx, current, buf); | 5521 smsg("%s%4d CMDMOD %s", pfx, current, buf); |
5514 vim_free(buf); | 5522 vim_free(buf); |