To: vim_dev@googlegroups.com Subject: Patch 8.2.0154 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0154 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. Files: src/globals.h, src/eval.c, src/evalvars.c, src/ex_docmd.c, src/profiler.c, src/scriptfile.c, src/vim9compile.c, src/vim9execute.c, src/vim9script.c *** ../vim-8.2.0153/src/globals.h 2020-01-26 15:52:33.019833259 +0100 --- src/globals.h 2020-01-26 19:10:11.521410270 +0100 *************** *** 285,293 **** # 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) # define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) # define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j] --- 285,293 ---- # ifdef FEAT_PROFILE EXTERN int do_profiling INIT(= PROF_NONE); // PROF_ values # endif ! 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] *** ../vim-8.2.0153/src/eval.c 2020-01-26 15:52:33.015833276 +0100 --- src/eval.c 2020-01-26 19:10:25.417373958 +0100 *************** *** 692,698 **** if (current_sctx.sc_version == SCRIPT_VERSION_VIM9 && *p == ':') { ! scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); char_u *tp = skipwhite(p + 1); // parse the type after the name --- 692,698 ---- if (current_sctx.sc_version == SCRIPT_VERSION_VIM9 && *p == ':') { ! scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); char_u *tp = skipwhite(p + 1); // parse the type after the name *** ../vim-8.2.0153/src/evalvars.c 2020-01-26 15:52:33.015833276 +0100 --- src/evalvars.c 2020-01-26 19:11:13.393244697 +0100 *************** *** 2289,2295 **** // imported variable from another script if (import != NULL) { ! 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; --- 2289,2295 ---- // imported variable from another script if (import != NULL) { ! 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,2577 **** if (sv == NULL) return; init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); ! SCRIPT_ITEM(id).sn_vars = sv; } /* --- 2571,2577 ---- if (sv == NULL) return; init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); ! SCRIPT_ITEM(id)->sn_vars = sv; } /* *************** *** 2876,2882 **** if (is_script_local && current_sctx.sc_version == SCRIPT_VERSION_VIM9) { ! 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. --- 2876,2882 ---- if (is_script_local && current_sctx.sc_version == SCRIPT_VERSION_VIM9) { ! 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. *** ../vim-8.2.0153/src/ex_docmd.c 2020-01-26 15:52:33.019833259 +0100 --- src/ex_docmd.c 2020-01-26 19:11:29.617199714 +0100 *************** *** 2496,2502 **** #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; /* * If the command just executed called do_cmdline(), any throw or ":return" --- 2496,2502 ---- #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; /* * If the command just executed called do_cmdline(), any throw or ":return" *** ../vim-8.2.0153/src/profiler.c 2019-12-29 23:04:20.294639884 +0100 --- src/profiler.c 2020-01-26 19:12:02.917105445 +0100 *************** *** 440,446 **** prof_def_func(void) { if (current_sctx.sc_sid > 0) ! return SCRIPT_ITEM(current_sctx.sc_sid).sn_pr_force; return FALSE; } --- 440,446 ---- prof_def_func(void) { if (current_sctx.sc_sid > 0) ! return SCRIPT_ITEM(current_sctx.sc_sid)->sn_pr_force; return FALSE; } *************** *** 763,769 **** if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { ! si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_pr_nest++ == 0) profile_start(&si->sn_pr_child); } --- 763,769 ---- if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { ! si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_pr_nest++ == 0) profile_start(&si->sn_pr_child); } *************** *** 780,786 **** if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { ! si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && --si->sn_pr_nest == 0) { profile_end(&si->sn_pr_child); --- 780,786 ---- if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { ! si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && --si->sn_pr_nest == 0) { profile_end(&si->sn_pr_child); *************** *** 805,811 **** for (id = 1; id <= script_items.ga_len; ++id) { ! si = &SCRIPT_ITEM(id); if (si->sn_prof_on) { fprintf(fd, "SCRIPT %s\n", si->sn_name); --- 805,811 ---- for (id = 1; id <= script_items.ga_len; ++id) { ! si = SCRIPT_ITEM(id); if (si->sn_prof_on) { fprintf(fd, "SCRIPT %s\n", si->sn_name); *************** *** 905,911 **** if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; ! 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 --- 905,911 ---- if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; ! 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,946 **** if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; ! si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_prl_idx >= 0) si->sn_prl_execed = TRUE; } --- 940,946 ---- if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; ! si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on && si->sn_prl_idx >= 0) si->sn_prl_execed = TRUE; } *************** *** 956,962 **** if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; ! 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) { --- 956,962 ---- if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; ! 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) { *** ../vim-8.2.0153/src/scriptfile.c 2020-01-26 17:38:07.824360503 +0100 --- src/scriptfile.c 2020-01-26 19:18:11.139931807 +0100 *************** *** 1124,1130 **** // 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); if (si->sn_name != NULL && fnamecmp(si->sn_name, fname_exp) == 0) // Found it! break; --- 1124,1130 ---- // 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); if (si->sn_name != NULL && fnamecmp(si->sn_name, fname_exp) == 0) // Found it! break; *************** *** 1294,1301 **** goto almosttheend; while (script_items.ga_len < current_sctx.sc_sid) { ++script_items.ga_len; ! si = &SCRIPT_ITEM(script_items.ga_len); si->sn_name = NULL; si->sn_version = 1; --- 1294,1304 ---- 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; ! SCRIPT_ITEM(script_items.ga_len) = si; si->sn_name = NULL; si->sn_version = 1; *************** *** 1308,1314 **** si->sn_prof_on = FALSE; # endif } ! 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) --- 1311,1317 ---- si->sn_prof_on = FALSE; # endif } ! 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,1370 **** if (do_profiling == PROF_YES) { // Get "si" again, "script_items" may have been reallocated. ! si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on) { profile_end(&si->sn_pr_start); --- 1367,1373 ---- if (do_profiling == PROF_YES) { // Get "si" again, "script_items" may have been reallocated. ! si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_prof_on) { profile_end(&si->sn_pr_start); *************** *** 1411,1417 **** #ifdef FEAT_EVAL almosttheend: // Get "si" again, "script_items" may have been reallocated. ! si = &SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_save_cpo != NULL) { free_string_option(p_cpo); --- 1414,1420 ---- #ifdef FEAT_EVAL almosttheend: // Get "si" again, "script_items" may have been reallocated. ! si = SCRIPT_ITEM(current_sctx.sc_sid); if (si->sn_save_cpo != NULL) { free_string_option(p_cpo); *************** *** 1456,1471 **** emsg(_(e_invarg)); else { ! 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) { ! home_replace(NULL, SCRIPT_ITEM(i).sn_name, NameBuff, MAXPATHL, TRUE); smsg("%3d: %s", i, NameBuff); } --- 1459,1474 ---- emsg(_(e_invarg)); else { ! 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) { ! home_replace(NULL, SCRIPT_ITEM(i)->sn_name, NameBuff, MAXPATHL, TRUE); smsg("%3d: %s", i, NameBuff); } *************** *** 1481,1488 **** 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); } # endif --- 1484,1491 ---- 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); } # endif *************** *** 1502,1508 **** return (char_u *)_("environment variable"); if (id == SID_ERROR) return (char_u *)_("error handler"); ! return SCRIPT_ITEM(id).sn_name; } # if defined(EXITFREE) || defined(PROTO) --- 1505,1511 ---- return (char_u *)_("environment variable"); if (id == SID_ERROR) return (char_u *)_("error handler"); ! return SCRIPT_ITEM(id)->sn_name; } # if defined(EXITFREE) || defined(PROTO) *************** *** 1513,1526 **** for (i = script_items.ga_len; i > 0; --i) { // the variables themselves are cleared in evalvars_clear() ! vim_free(SCRIPT_ITEM(i).sn_vars); ! vim_free(SCRIPT_ITEM(i).sn_name); ! free_string_option(SCRIPT_ITEM(i).sn_save_cpo); # ifdef FEAT_PROFILE ! ga_clear(&SCRIPT_ITEM(i).sn_prl_ga); # endif } ga_clear(&script_items); } --- 1516,1532 ---- 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(si->sn_vars); ! vim_free(si->sn_name); ! free_string_option(si->sn_save_cpo); # ifdef FEAT_PROFILE ! ga_clear(&si->sn_prl_ga); # endif + vim_free(si); } ga_clear(&script_items); } *************** *** 1832,1838 **** else { current_sctx.sc_version = nr; ! SCRIPT_ITEM(current_sctx.sc_sid).sn_version = nr; } #endif } --- 1838,1844 ---- else { current_sctx.sc_version = nr; ! SCRIPT_ITEM(current_sctx.sc_sid)->sn_version = nr; } #endif } *** ../vim-8.2.0153/src/vim9compile.c 2020-01-26 15:52:33.027833222 +0100 --- src/vim9compile.c 2020-01-26 19:13:15.168893009 +0100 *************** *** 1401,1407 **** { hashtab_T *ht; dictitem_T *di; ! scriptitem_T *si = &SCRIPT_ITEM(sid); int idx; // First look the name up in the hashtable. --- 1401,1407 ---- { hashtab_T *ht; dictitem_T *di; ! scriptitem_T *si = SCRIPT_ITEM(sid); int idx; // First look the name up in the hashtable. *************** *** 1433,1439 **** imported_T * find_imported(char_u *name, cctx_T *cctx) { ! scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); int idx; if (cctx != NULL) --- 1433,1439 ---- imported_T * find_imported(char_u *name, cctx_T *cctx) { ! scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); int idx; if (cctx != NULL) *************** *** 1462,1468 **** static int compile_load_scriptvar(cctx_T *cctx, char_u *name) { ! scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE); imported_T *import; --- 1462,1468 ---- static int compile_load_scriptvar(cctx_T *cctx, char_u *name) { ! scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); int idx = get_script_item_idx(current_sctx.sc_sid, name, FALSE); imported_T *import; *** ../vim-8.2.0153/src/vim9execute.c 2020-01-26 15:52:33.027833222 +0100 --- src/vim9execute.c 2020-01-26 19:13:50.856784257 +0100 *************** *** 492,498 **** case ISN_LOADSCRIPT: { scriptitem_T *si = ! &SCRIPT_ITEM(iptr->isn_arg.script.script_sid); svar_T *sv; sv = ((svar_T *)si->sn_var_vals.ga_data) --- 492,498 ---- case ISN_LOADSCRIPT: { scriptitem_T *si = ! SCRIPT_ITEM(iptr->isn_arg.script.script_sid); svar_T *sv; sv = ((svar_T *)si->sn_var_vals.ga_data) *************** *** 598,604 **** // store script-local variable case ISN_STORESCRIPT: { ! 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; --- 598,604 ---- // store script-local variable case ISN_STORESCRIPT: { ! 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,1557 **** case ISN_LOADSCRIPT: { 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,1557 ---- case ISN_LOADSCRIPT: { 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; *************** *** 1561,1567 **** break; case ISN_LOADS: { ! 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); --- 1561,1567 ---- break; case ISN_LOADS: { ! 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,1595 **** case ISN_STORESCRIPT: { 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; --- 1589,1595 ---- case ISN_STORESCRIPT: { 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; *** ../vim-8.2.0153/src/vim9script.c 2020-01-26 15:52:33.027833222 +0100 --- src/vim9script.c 2020-01-26 19:19:54.571570538 +0100 *************** *** 32,38 **** void ex_vim9script(exarg_T *eap) { ! scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); if (!getline_equal(eap->getline, eap->cookie, getsourceline)) { --- 32,38 ---- void ex_vim9script(exarg_T *eap) { ! scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); if (!getline_equal(eap->getline, eap->cookie, getsourceline)) { *************** *** 114,120 **** void free_imports(int sid) { ! scriptitem_T *si = &SCRIPT_ITEM(sid); int idx; for (idx = 0; idx < si->sn_imports.ga_len; ++idx) --- 114,120 ---- void free_imports(int sid) { ! scriptitem_T *si = SCRIPT_ITEM(sid); int idx; for (idx = 0; idx < si->sn_imports.ga_len; ++idx) *************** *** 226,232 **** if (*tv.vval.v_string == '.') { size_t len; ! scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid); char_u *tail = gettail(si->sn_name); char_u *from_name; --- 226,232 ---- if (*tv.vval.v_string == '.') { size_t len; ! scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); char_u *tail = gettail(si->sn_name); char_u *from_name; *************** *** 279,285 **** if (*arg_start == '*') { imported_T *imported = new_imported(gap != NULL ? gap ! : &SCRIPT_ITEM(import_sid).sn_imports); if (imported == NULL) return NULL; --- 279,285 ---- if (*arg_start == '*') { imported_T *imported = new_imported(gap != NULL ? gap ! : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL) return NULL; *************** *** 289,295 **** } else { ! scriptitem_T *script = &SCRIPT_ITEM(sid); arg = arg_start; if (*arg == '{') --- 289,295 ---- } else { ! scriptitem_T *script = SCRIPT_ITEM(sid); arg = arg_start; if (*arg == '{') *************** *** 358,364 **** } imported = new_imported(gap != NULL ? gap ! : &SCRIPT_ITEM(import_sid).sn_imports); if (imported == NULL) return NULL; --- 358,364 ---- } imported = new_imported(gap != NULL ? gap ! : &SCRIPT_ITEM(import_sid)->sn_imports); if (imported == NULL) return NULL; *** ../vim-8.2.0153/src/version.c 2020-01-26 18:56:31.084689678 +0100 --- src/version.c 2020-01-26 19:26:07.182202875 +0100 *************** *** 744,745 **** --- 744,747 ---- { /* Add new patch number below this line */ + /**/ + 154, /**/ -- An alien life briefly visits earth. Just before departing it leaves a message in the dust on the back of a white van. The world is shocked and wants to know what it means. After months of studies the worlds best linguistic scientists are able to decipher the message: "Wash me!". /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///