# HG changeset patch # User Bram Moolenaar # Date 1580063414 -3600 # Node ID 133ef7ba4e4e8280163df3b9238ed26992e62e2e # Parent 1483c87623da68c4378c208f7b894be886f983a9 patch 8.2.0154: reallocating the list of scripts is inefficient Commit: https://github.com/vim/vim/commit/21b9e9773d64de40994f8762173bdd8befa6acf7 Author: Bram Moolenaar Date: Sun Jan 26 19:26:46 2020 +0100 patch 8.2.0154: reallocating the list of scripts is inefficient Problem: Reallocating the list of scripts is inefficient. Solution: Instead of using a growarray of scriptitem_T, store pointers and allocate each scriptitem_T separately. Also avoids that the growarray pointers change when sourcing a new script. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -692,7 +692,7 @@ get_lval( if (current_sctx.sc_version == SCRIPT_VERSION_VIM9 && *p == ':') { - scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); char_u *tp = skipwhite(p + 1); // parse the type after the name diff --git a/src/evalvars.c b/src/evalvars.c --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2289,7 +2289,7 @@ get_var_tv( // imported variable from another script if (import != NULL) { - scriptitem_T *si = &SCRIPT_ITEM(import->imp_sid); + scriptitem_T *si = SCRIPT_ITEM(import->imp_sid); svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + import->imp_var_vals_idx; tv = sv->sv_tv; @@ -2571,7 +2571,7 @@ new_script_vars(scid_T id) if (sv == NULL) return; init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); - SCRIPT_ITEM(id).sn_vars = sv; + SCRIPT_ITEM(id)->sn_vars = sv; } /* @@ -2876,7 +2876,7 @@ set_var_const( if (is_script_local && current_sctx.sc_version == SCRIPT_VERSION_VIM9) { - scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); // Store a pointer to the typval_T, so that it can be found by // index instead of using a hastab lookup. diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -2496,7 +2496,7 @@ do_one_cmd( #ifdef FEAT_EVAL // Set flag that any command was executed, used by ex_vim9script(). if (getline_equal(ea.getline, ea.cookie, getsourceline)) - SCRIPT_ITEM(current_sctx.sc_sid).sn_had_command = TRUE; + SCRIPT_ITEM(current_sctx.sc_sid)->sn_had_command = TRUE; /* * If the command just executed called do_cmdline(), any throw or ":return" diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -285,9 +285,9 @@ EXTERN int debug_backtrace_level INIT(= # ifdef FEAT_PROFILE EXTERN int do_profiling INIT(= PROF_NONE); // PROF_ values # endif -EXTERN garray_T script_items INIT5(0, 0, sizeof(scriptitem_T), 4, NULL); -# define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1]) -# define SCRIPT_SV(id) (SCRIPT_ITEM(id).sn_vars) +EXTERN garray_T script_items INIT5(0, 0, sizeof(scriptitem_T *), 20, NULL); +# define SCRIPT_ITEM(id) (((scriptitem_T **)script_items.ga_data)[(id) - 1]) +# define SCRIPT_SV(id) (SCRIPT_ITEM(id)->sn_vars) # define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) # define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] diff --git a/src/profiler.c b/src/profiler.c --- a/src/profiler.c +++ b/src/profiler.c @@ -440,7 +440,7 @@ prof_inchar_exit(void) prof_def_func(void) { if (current_sctx.sc_sid > 0) - return SCRIPT_ITEM(current_sctx.sc_sid).sn_pr_force; + return SCRIPT_ITEM(current_sctx.sc_sid)->sn_pr_force; return FALSE; } @@ -763,7 +763,7 @@ script_prof_save( if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_pr_nest++ == 0) profile_start(&si->sn_pr_child); } @@ -780,7 +780,7 @@ script_prof_restore(proftime_T *tm) if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && --si->sn_pr_nest == 0) { profile_end(&si->sn_pr_child); @@ -805,7 +805,7 @@ script_dump_profile(FILE *fd) for (id = 1; id <= script_items.ga_len; ++id) { - si = &SCRIPT_ITEM(id); + si = SCRIPT_ITEM(id); if (si->sn_prof_on) { fprintf(fd, "SCRIPT %s\n", si->sn_name); @@ -905,7 +905,7 @@ script_line_start(void) if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && SOURCING_LNUM >= 1) { // Grow the array before starting the timer, so that the time spent @@ -940,7 +940,7 @@ script_line_exec(void) if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_prl_idx >= 0) si->sn_prl_execed = TRUE; } @@ -956,7 +956,7 @@ script_line_end(void) if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_prl_idx >= 0 && si->sn_prl_idx < si->sn_prl_ga.ga_len) { diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1124,7 +1124,7 @@ do_source( // inode number, even though to the user it is the same script. // - If a script is deleted and another script is written, with a // different name, the inode may be re-used. - si = &SCRIPT_ITEM(sid); + si = SCRIPT_ITEM(sid); if (si->sn_name != NULL && fnamecmp(si->sn_name, fname_exp) == 0) // Found it! break; @@ -1294,8 +1294,11 @@ do_source( goto almosttheend; while (script_items.ga_len < current_sctx.sc_sid) { + si = ALLOC_CLEAR_ONE(scriptitem_T); + if (si == NULL) + goto almosttheend; ++script_items.ga_len; - si = &SCRIPT_ITEM(script_items.ga_len); + SCRIPT_ITEM(script_items.ga_len) = si; si->sn_name = NULL; si->sn_version = 1; @@ -1308,7 +1311,7 @@ do_source( si->sn_prof_on = FALSE; # endif } - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); si->sn_name = fname_exp; fname_exp = vim_strsave(si->sn_name); // used for autocmd if (ret_sid != NULL) @@ -1364,7 +1367,7 @@ do_source( if (do_profiling == PROF_YES) { // Get "si" again, "script_items" may have been reallocated. - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on) { profile_end(&si->sn_pr_start); @@ -1411,7 +1414,7 @@ do_source( #ifdef FEAT_EVAL almosttheend: // Get "si" again, "script_items" may have been reallocated. - si = &SCRIPT_ITEM(current_sctx.sc_sid); + si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_save_cpo != NULL) { free_string_option(p_cpo); @@ -1456,16 +1459,16 @@ ex_scriptnames(exarg_T *eap) emsg(_(e_invarg)); else { - eap->arg = SCRIPT_ITEM(eap->line2).sn_name; + eap->arg = SCRIPT_ITEM(eap->line2)->sn_name; do_exedit(eap, NULL); } return; } for (i = 1; i <= script_items.ga_len && !got_int; ++i) - if (SCRIPT_ITEM(i).sn_name != NULL) + if (SCRIPT_ITEM(i)->sn_name != NULL) { - home_replace(NULL, SCRIPT_ITEM(i).sn_name, + home_replace(NULL, SCRIPT_ITEM(i)->sn_name, NameBuff, MAXPATHL, TRUE); smsg("%3d: %s", i, NameBuff); } @@ -1481,8 +1484,8 @@ scriptnames_slash_adjust(void) int i; for (i = 1; i <= script_items.ga_len; ++i) - if (SCRIPT_ITEM(i).sn_name != NULL) - slash_adjust(SCRIPT_ITEM(i).sn_name); + if (SCRIPT_ITEM(i)->sn_name != NULL) + slash_adjust(SCRIPT_ITEM(i)->sn_name); } # endif @@ -1502,7 +1505,7 @@ get_scriptname(scid_T id) return (char_u *)_("environment variable"); if (id == SID_ERROR) return (char_u *)_("error handler"); - return SCRIPT_ITEM(id).sn_name; + return SCRIPT_ITEM(id)->sn_name; } # if defined(EXITFREE) || defined(PROTO) @@ -1513,14 +1516,17 @@ free_scriptnames(void) for (i = script_items.ga_len; i > 0; --i) { + scriptitem_T *si = SCRIPT_ITEM(i); + // the variables themselves are cleared in evalvars_clear() - vim_free(SCRIPT_ITEM(i).sn_vars); + vim_free(si->sn_vars); - vim_free(SCRIPT_ITEM(i).sn_name); - free_string_option(SCRIPT_ITEM(i).sn_save_cpo); + vim_free(si->sn_name); + free_string_option(si->sn_save_cpo); # ifdef FEAT_PROFILE - ga_clear(&SCRIPT_ITEM(i).sn_prl_ga); + ga_clear(&si->sn_prl_ga); # endif + vim_free(si); } ga_clear(&script_items); } @@ -1832,7 +1838,7 @@ ex_scriptversion(exarg_T *eap UNUSED) else { current_sctx.sc_version = nr; - SCRIPT_ITEM(current_sctx.sc_sid).sn_version = nr; + SCRIPT_ITEM(current_sctx.sc_sid)->sn_version = nr; } #endif } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 154, +/**/ 153, /**/ 152, diff --git a/src/vim9compile.c b/src/vim9compile.c --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1401,7 +1401,7 @@ get_script_item_idx(int sid, char_u *nam { hashtab_T *ht; dictitem_T *di; - scriptitem_T *si = &SCRIPT_ITEM(sid); + scriptitem_T *si = SCRIPT_ITEM(sid); int idx; // First look the name up in the hashtable. @@ -1433,7 +1433,7 @@ get_script_item_idx(int sid, char_u *nam imported_T * find_imported(char_u *name, cctx_T *cctx) { - scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); int idx; if (cctx != NULL) @@ -1462,7 +1462,7 @@ find_imported(char_u *name, cctx_T *cctx static int compile_load_scriptvar(cctx_T *cctx, char_u *name) { - scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE); imported_T *import; diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -492,7 +492,7 @@ call_def_function( case ISN_LOADSCRIPT: { scriptitem_T *si = - &SCRIPT_ITEM(iptr->isn_arg.script.script_sid); + SCRIPT_ITEM(iptr->isn_arg.script.script_sid); svar_T *sv; sv = ((svar_T *)si->sn_var_vals.ga_data) @@ -598,7 +598,7 @@ call_def_function( // store script-local variable case ISN_STORESCRIPT: { - scriptitem_T *si = &SCRIPT_ITEM( + scriptitem_T *si = SCRIPT_ITEM( iptr->isn_arg.script.script_sid); svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + iptr->isn_arg.script.script_idx; @@ -1551,7 +1551,7 @@ ex_disassemble(exarg_T *eap) case ISN_LOADSCRIPT: { scriptitem_T *si = - &SCRIPT_ITEM(iptr->isn_arg.script.script_sid); + SCRIPT_ITEM(iptr->isn_arg.script.script_sid); svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + iptr->isn_arg.script.script_idx; @@ -1561,7 +1561,7 @@ ex_disassemble(exarg_T *eap) break; case ISN_LOADS: { - scriptitem_T *si = &SCRIPT_ITEM(iptr->isn_arg.loads.ls_sid); + scriptitem_T *si = SCRIPT_ITEM(iptr->isn_arg.loads.ls_sid); smsg("%4d LOADS s:%s from %s", current, iptr->isn_arg.string, si->sn_name); @@ -1589,7 +1589,7 @@ ex_disassemble(exarg_T *eap) case ISN_STORESCRIPT: { scriptitem_T *si = - &SCRIPT_ITEM(iptr->isn_arg.script.script_sid); + SCRIPT_ITEM(iptr->isn_arg.script.script_sid); svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + iptr->isn_arg.script.script_idx; diff --git a/src/vim9script.c b/src/vim9script.c --- a/src/vim9script.c +++ b/src/vim9script.c @@ -32,7 +32,7 @@ in_vim9script(void) void ex_vim9script(exarg_T *eap) { - scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); if (!getline_equal(eap->getline, eap->cookie, getsourceline)) { @@ -114,7 +114,7 @@ new_imported(garray_T *gap) void free_imports(int sid) { - scriptitem_T *si = &SCRIPT_ITEM(sid); + scriptitem_T *si = SCRIPT_ITEM(sid); int idx; for (idx = 0; idx < si->sn_imports.ga_len; ++idx) @@ -226,7 +226,7 @@ handle_import(char_u *arg_start, garray_ if (*tv.vval.v_string == '.') { size_t len; - scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); char_u *tail = gettail(si->sn_name); char_u *from_name; @@ -279,7 +279,7 @@ handle_import(char_u *arg_start, garray_ if (*arg_start == '*') { imported_T *imported = new_imported(gap != NULL ? gap - : &SCRIPT_ITEM(import_sid).sn_imports); + : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL) return NULL; @@ -289,7 +289,7 @@ handle_import(char_u *arg_start, garray_ } else { - scriptitem_T *script = &SCRIPT_ITEM(sid); + scriptitem_T *script = SCRIPT_ITEM(sid); arg = arg_start; if (*arg == '{') @@ -358,7 +358,7 @@ handle_import(char_u *arg_start, garray_ } imported = new_imported(gap != NULL ? gap - : &SCRIPT_ITEM(import_sid).sn_imports); + : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL) return NULL;