aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c73
-rw-r--r--src/nvim/runtime.c14
-rw-r--r--src/nvim/runtime.h11
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