aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-02-16 11:00:48 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-02-16 11:50:28 +0800
commit0cbbe27e93e87a5336673e0529b011313c51a123 (patch)
tree1a5a45358dc499a7b620c0b6b0887aafd98c8f3f
parente619fb1660595f9e6a0afad8d9a91e37a94f95a3 (diff)
downloadrneovim-0cbbe27e93e87a5336673e0529b011313c51a123.tar.gz
rneovim-0cbbe27e93e87a5336673e0529b011313c51a123.tar.bz2
rneovim-0cbbe27e93e87a5336673e0529b011313c51a123.zip
vim-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. https://github.com/vim/vim/commit/21b9e9773d64de40994f8762173bdd8befa6acf7 Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r--src/nvim/cmdexpand.c2
-rw-r--r--src/nvim/eval.c4
-rw-r--r--src/nvim/profile.c22
-rw-r--r--src/nvim/runtime.c40
-rw-r--r--src/nvim/runtime.h2
5 files changed, 34 insertions, 36 deletions
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index 97feab2978..fcd6a73b2d 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -2524,7 +2524,7 @@ static char *get_scriptnames_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
return NULL;
}
- scriptitem_T *si = &SCRIPT_ITEM(idx + 1);
+ scriptitem_T *si = SCRIPT_ITEM(idx + 1);
home_replace(NULL, si->sn_name, NameBuff, MAXPATHL, true);
return NameBuff;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a09bd72710..92a8ffd646 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -109,7 +109,7 @@ static hashtab_T compat_hashtab;
/// Used for checking if local variables or arguments used in a lambda.
bool *eval_lavars_used = NULL;
-#define SCRIPT_SV(id) (SCRIPT_ITEM(id).sn_vars)
+#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"
@@ -7177,7 +7177,7 @@ void new_script_vars(scid_T id)
{
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;
+ SCRIPT_ITEM(id)->sn_vars = sv;
}
/// Initialize dictionary "dict" as a scope and set variable "dict_var" to
diff --git a/src/nvim/profile.c b/src/nvim/profile.c
index 173332a428..6b841bd961 100644
--- a/src/nvim/profile.c
+++ b/src/nvim/profile.c
@@ -232,7 +232,7 @@ void profile_reset(void)
{
// Reset sourced files.
for (int id = 1; id <= script_items.ga_len; id++) {
- scriptitem_T *si = &SCRIPT_ITEM(id);
+ scriptitem_T *si = SCRIPT_ITEM(id);
if (si->sn_prof_on) {
si->sn_prof_on = false;
si->sn_pr_force = false;
@@ -407,7 +407,7 @@ bool prof_def_func(void)
FUNC_ATTR_PURE
{
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;
}
@@ -690,7 +690,7 @@ void profile_init(scriptitem_T *si)
void script_prof_save(proftime_T *tm)
{
if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) {
- scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
if (si->sn_prof_on && si->sn_pr_nest++ == 0) {
si->sn_pr_child = profile_start();
}
@@ -705,7 +705,7 @@ void script_prof_restore(const proftime_T *tm)
return;
}
- scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
if (si->sn_prof_on && --si->sn_pr_nest == 0) {
si->sn_pr_child = profile_end(si->sn_pr_child);
// don't count wait time
@@ -722,7 +722,7 @@ static void script_dump_profile(FILE *fd)
sn_prl_T *pp;
for (int id = 1; id <= script_items.ga_len; id++) {
- scriptitem_T *si = &SCRIPT_ITEM(id);
+ scriptitem_T *si = SCRIPT_ITEM(id);
if (si->sn_prof_on) {
fprintf(fd, "SCRIPT %s\n", si->sn_name);
if (si->sn_pr_count == 1) {
@@ -804,12 +804,10 @@ void profile_dump(void)
/// until later and we need to store the time now.
void script_line_start(void)
{
- scriptitem_T *si;
-
if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) {
return;
}
- si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ scriptitem_T *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
// here isn't counted.
@@ -834,12 +832,10 @@ void script_line_start(void)
/// Called when actually executing a function line.
void script_line_exec(void)
{
- scriptitem_T *si;
-
if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) {
return;
}
- si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
if (si->sn_prof_on && si->sn_prl_idx >= 0) {
si->sn_prl_execed = true;
}
@@ -848,12 +844,10 @@ void script_line_exec(void)
/// Called when done with a function line.
void script_line_end(void)
{
- scriptitem_T *si;
-
if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) {
return;
}
- si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ scriptitem_T *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) {
if (si->sn_prl_execed) {
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index e8b0492f35..9dc213d718 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -73,7 +73,7 @@ struct source_cookie {
#endif
garray_T exestack = { 0, 0, sizeof(estack_T), 50, NULL };
-garray_T script_items = { 0, 0, sizeof(scriptitem_T), 4, NULL };
+garray_T script_items = { 0, 0, sizeof(scriptitem_T *), 20, NULL };
/// Initialize the execution stack.
void estack_init(void)
@@ -144,7 +144,7 @@ char *estack_sfile(estack_arg_T which)
? &entry->es_info.ufunc->uf_script_ctx
: &entry->es_info.aucmd->script_ctx);
return def_ctx->sc_sid > 0
- ? xstrdup((SCRIPT_ITEM(def_ctx->sc_sid).sn_name))
+ ? xstrdup((SCRIPT_ITEM(def_ctx->sc_sid)->sn_name))
: NULL;
} else if (entry->es_type == ETYPE_SCRIPT) {
return xstrdup(entry->es_name);
@@ -1844,16 +1844,18 @@ scriptitem_T *new_script_item(char *const name, scid_T *const sid_out)
}
ga_grow(&script_items, sid - script_items.ga_len);
while (script_items.ga_len < sid) {
+ scriptitem_T *si = xcalloc(1, sizeof(scriptitem_T));
script_items.ga_len++;
- SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
+ SCRIPT_ITEM(script_items.ga_len) = si;
+ si->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;
+ si->sn_prof_on = false;
}
- SCRIPT_ITEM(sid).sn_name = name;
- return &SCRIPT_ITEM(sid);
+ SCRIPT_ITEM(sid)->sn_name = name;
+ return SCRIPT_ITEM(sid);
}
static int source_using_linegetter(void *cookie, LineGetter fgetline, const char *traceback_name)
@@ -2121,7 +2123,7 @@ int do_source(char *fname, int check_other, int is_vimrc)
if (l_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) {
si->sn_pr_start = profile_end(si->sn_pr_start);
si->sn_pr_start = profile_sub_wait(wait_start, si->sn_pr_start);
@@ -2201,7 +2203,7 @@ scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx)
// 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(script_sctx.sc_sid);
+ si = SCRIPT_ITEM(script_sctx.sc_sid);
if (si->sn_name != NULL && path_fnamecmp(si->sn_name, *fnamep) == 0) {
// Found it!
break;
@@ -2227,7 +2229,7 @@ void ex_scriptnames(exarg_T *eap)
emsg(_(e_invarg));
} else {
if (eap->addr_count > 0) {
- eap->arg = SCRIPT_ITEM(eap->line2).sn_name;
+ eap->arg = SCRIPT_ITEM(eap->line2)->sn_name;
} else {
expand_env(eap->arg, NameBuff, MAXPATHL);
eap->arg = NameBuff;
@@ -2238,8 +2240,8 @@ void ex_scriptnames(exarg_T *eap)
}
for (int 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);
+ if (SCRIPT_ITEM(i)->sn_name != NULL) {
+ home_replace(NULL, SCRIPT_ITEM(i)->sn_name, NameBuff, MAXPATHL, true);
vim_snprintf(IObuff, IOSIZE, "%3d: %s", i, NameBuff);
if (!message_filtered(IObuff)) {
msg_putchar('\n');
@@ -2255,8 +2257,8 @@ void ex_scriptnames(exarg_T *eap)
void scriptnames_slash_adjust(void)
{
for (int 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);
}
}
}
@@ -2290,7 +2292,7 @@ char *get_scriptname(LastSet last_set, bool *should_free)
case SID_STR:
return _("anonymous :source");
default: {
- char *const sname = SCRIPT_ITEM(last_set.script_ctx.sc_sid).sn_name;
+ char *const sname = SCRIPT_ITEM(last_set.script_ctx.sc_sid)->sn_name;
if (sname == NULL) {
snprintf(IObuff, IOSIZE, _("anonymous :source (script id %d)"),
last_set.script_ctx.sc_sid);
@@ -2310,13 +2312,15 @@ void free_scriptnames(void)
# define FREE_SCRIPTNAME(item) \
do { \
+ scriptitem_T *_si = *(item); \
/* the variables themselves are cleared in evalvars_clear() */ \
- xfree((item)->sn_vars); \
- xfree((item)->sn_name); \
- ga_clear(&(item)->sn_prl_ga); \
+ xfree(_si->sn_vars); \
+ xfree(_si->sn_name); \
+ ga_clear(&_si->sn_prl_ga); \
+ xfree(_si); \
} while (0) \
- GA_DEEP_CLEAR(&script_items, scriptitem_T, FREE_SCRIPTNAME);
+ GA_DEEP_CLEAR(&script_items, scriptitem_T *, FREE_SCRIPTNAME);
}
#endif
diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h
index 0812355716..9a810298f8 100644
--- a/src/nvim/runtime.h
+++ b/src/nvim/runtime.h
@@ -87,7 +87,7 @@ typedef struct {
/// Growarray to store info about already sourced scripts.
extern garray_T script_items;
-#define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1])
+#define SCRIPT_ITEM(id) (((scriptitem_T **)script_items.ga_data)[(id) - 1])
#define SCRIPT_ID_VALID(id) ((id) > 0 && (id) <= script_items.ga_len)
typedef void (*DoInRuntimepathCB)(char *, void *);