diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 73 | ||||
-rw-r--r-- | src/nvim/runtime.c | 14 | ||||
-rw-r--r-- | src/nvim/runtime.h | 11 |
3 files changed, 46 insertions, 52 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 3ab704e250..a09bd72710 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -109,15 +109,7 @@ static hashtab_T compat_hashtab; /// Used for checking if local variables or arguments used in a lambda. bool *eval_lavars_used = NULL; -/// Array to hold the hashtab with variables local to each sourced script. -/// Each item holds a variable (nameless) that points to the dict_T. -typedef struct { - ScopeDictDictItem sv_var; - dict_T sv_dict; -} scriptvar_T; - -static garray_T ga_scripts = { 0, 0, sizeof(scriptvar_T *), 4, NULL }; -#define SCRIPT_SV(id) (((scriptvar_T **)ga_scripts.ga_data)[(id) - 1]) +#define SCRIPT_SV(id) (SCRIPT_ITEM(id).sn_vars) #define SCRIPT_VARS(id) (SCRIPT_SV(id)->sv_dict.dv_hashtab) static int echo_attr = 0; // attributes used for ":echo" @@ -473,7 +465,7 @@ void eval_init(void) } #if defined(EXITFREE) -void eval_clear(void) +static void evalvars_clear(void) { for (size_t i = 0; i < ARRAY_SIZE(vimvars); i++) { struct vimvar *p = &vimvars[i]; @@ -488,28 +480,29 @@ void eval_clear(void) hash_init(&vimvarht); // garbage_collect() will access it hash_clear(&compat_hashtab); - free_scriptnames(); + // global variables + vars_clear(&globvarht); + + // Script-local variables. Clear all the variables here. + // The scriptvar_T is cleared later in free_scriptnames(), because a + // variable in one script might hold a reference to the whole scope of + // another script. + for (int i = 1; i <= script_items.ga_len; i++) { + vars_clear(&SCRIPT_VARS(i)); + } +} + +void eval_clear(void) +{ + evalvars_clear(); + free_scriptnames(); // must come after evalvars_clear(). # ifdef HAVE_WORKING_LIBINTL free_locales(); # endif - // global variables - vars_clear(&globvarht); - // autoloaded script names ga_clear_strings(&ga_loaded); - // Script-local variables. First clear all the variables and in a second - // loop free the scriptvar_T, because a variable in one script might hold - // a reference to the whole scope of another script. - for (int i = 1; i <= ga_scripts.ga_len; i++) { - vars_clear(&SCRIPT_VARS(i)); - } - for (int i = 1; i <= ga_scripts.ga_len; i++) { - xfree(SCRIPT_SV(i)); - } - ga_clear(&ga_scripts); - // unreferenced lists and dicts (void)garbage_collect(false); @@ -970,7 +963,7 @@ void list_vim_vars(int *first) /// List script-local variables, if there is a script. void list_script_vars(int *first) { - if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len) { + if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) { list_hashtable_vars(&SCRIPT_VARS(current_sctx.sc_sid), "s:", false, first); } } @@ -4116,7 +4109,7 @@ bool garbage_collect(bool testing) ABORTING(set_ref_in_previous_funccal)(copyID); // script-local variables - for (int i = 1; i <= ga_scripts.ga_len; i++) { + for (int i = 1; i <= script_items.ga_len; i++) { ABORTING(set_ref_in_ht)(&SCRIPT_VARS(i), copyID, NULL); } @@ -7131,7 +7124,7 @@ hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char } else if (*name == 's' // script variable && (current_sctx.sc_sid > 0 || current_sctx.sc_sid == SID_STR || current_sctx.sc_sid == SID_LUA) - && current_sctx.sc_sid <= ga_scripts.ga_len) { + && current_sctx.sc_sid <= script_items.ga_len) { // For anonymous scripts without a script item, create one now so script vars can be used if (current_sctx.sc_sid == SID_LUA) { // try to resolve lua filename & line no so it can be shown in lastset messages. @@ -7182,27 +7175,9 @@ hashtab_T *find_var_ht(const char *name, const size_t name_len, const char **var /// sourcing this script and when executing functions defined in the script. void new_script_vars(scid_T id) { - scriptvar_T *sv; - - ga_grow(&ga_scripts, id - ga_scripts.ga_len); - - // Re-allocating ga_data means that an ht_array pointing to - // ht_smallarray becomes invalid. We can recognize this: ht_mask is - // at its init value. Also reset "v_dict", it's always the same. - for (int i = 1; i <= ga_scripts.ga_len; i++) { - hashtab_T *ht = &SCRIPT_VARS(i); - if (ht->ht_mask == HT_INIT_SIZE - 1) { - ht->ht_array = ht->ht_smallarray; - } - sv = SCRIPT_SV(i); - sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict; - } - - while (ga_scripts.ga_len < id) { - sv = SCRIPT_SV(ga_scripts.ga_len + 1) = xcalloc(1, sizeof(scriptvar_T)); - init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); - ga_scripts.ga_len++; - } + scriptvar_T *sv = xcalloc(1, sizeof(scriptvar_T)); + init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE); + SCRIPT_ITEM(id).sn_vars = sv; } /// Initialize dictionary "dict" as a scope and set variable "dict_var" to diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index cff0f886ce..e8b0492f35 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -1846,10 +1846,13 @@ scriptitem_T *new_script_item(char *const name, scid_T *const sid_out) while (script_items.ga_len < sid) { script_items.ga_len++; SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; + + // Allocate the local script variables to use for this script. + new_script_vars(script_items.ga_len); + SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false; } SCRIPT_ITEM(sid).sn_name = name; - new_script_vars(sid); // Allocate the local script variables to use for this script. return &SCRIPT_ITEM(sid); } @@ -2305,7 +2308,14 @@ void free_scriptnames(void) { profile_reset(); -# define FREE_SCRIPTNAME(item) xfree((item)->sn_name) +# define FREE_SCRIPTNAME(item) \ + do { \ + /* the variables themselves are cleared in evalvars_clear() */ \ + xfree((item)->sn_vars); \ + xfree((item)->sn_name); \ + ga_clear(&(item)->sn_prl_ga); \ + } while (0) \ + GA_DEEP_CLEAR(&script_items, scriptitem_T, FREE_SCRIPTNAME); } #endif diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h index 97063b900c..0812355716 100644 --- a/src/nvim/runtime.h +++ b/src/nvim/runtime.h @@ -55,7 +55,16 @@ typedef enum { ESTACK_SCRIPT, } estack_arg_T; -typedef struct scriptitem_S { +/// Holds the hashtab with variables local to each sourced script. +/// Each item holds a variable (nameless) that points to the dict_T. +typedef struct { + ScopeDictDictItem sv_var; + dict_T sv_dict; +} scriptvar_T; + +typedef struct { + scriptvar_T *sn_vars; ///< stores s: variables for this script + char *sn_name; bool sn_prof_on; ///< true when script is/was profiled bool sn_pr_force; ///< forceit: profile functions in this script |