aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-12-17 09:28:44 +0800
committerGitHub <noreply@github.com>2022-12-17 09:28:44 +0800
commit2d8bbe468e796137ae1b5f504b3d73758a8c391c (patch)
treed89eb7439ff0632dfe136a4da55c494f3ba0039b
parent4d860a537076d7eddfb29372ecbdacf1eb5b7d3b (diff)
parentb969844398bc8d6021f8da286819c22aa73e1535 (diff)
downloadrneovim-2d8bbe468e796137ae1b5f504b3d73758a8c391c.tar.gz
rneovim-2d8bbe468e796137ae1b5f504b3d73758a8c391c.tar.bz2
rneovim-2d8bbe468e796137ae1b5f504b3d73758a8c391c.zip
Merge pull request #21450 from zeertzjq/vim-8.2.1210
vim-patch:8.2.{1208,1209,1210}: using ht_used when looping through a hashtab is less reliable
-rw-r--r--src/nvim/eval/userfunc.c16
-rw-r--r--src/nvim/hashtab.c3
-rw-r--r--src/nvim/hashtab.h17
3 files changed, 21 insertions, 15 deletions
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index a37613dca9..69b074ab99 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -1297,7 +1297,7 @@ void free_all_functions(void)
ufunc_T *fp;
uint64_t skipped = 0;
uint64_t todo = 1;
- uint64_t used;
+ int changed;
// Clean up the current_funccal chain and the funccal stack.
while (current_funccal != NULL) {
@@ -1321,9 +1321,9 @@ void free_all_functions(void)
if (func_name_refcount((char_u *)fp->uf_name)) {
skipped++;
} else {
- used = func_hashtab.ht_used;
+ changed = func_hashtab.ht_changed;
func_clear(fp, true);
- if (used != func_hashtab.ht_used) {
+ if (changed != func_hashtab.ht_changed) {
skipped = 0;
break;
}
@@ -1993,8 +1993,8 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi)
/// Otherwise functions matching "regmatch".
static void list_functions(regmatch_T *regmatch)
{
- const size_t used = func_hashtab.ht_used;
- size_t todo = used;
+ const int changed = func_hashtab.ht_changed;
+ size_t todo = func_hashtab.ht_used;
const hashitem_T *const ht_array = func_hashtab.ht_array;
for (const hashitem_T *hi = ht_array; todo > 0 && !got_int; hi++) {
@@ -2008,7 +2008,7 @@ static void list_functions(regmatch_T *regmatch)
: (!isdigit(*fp->uf_name)
&& vim_regexec(regmatch, (char *)fp->uf_name, 0)))) {
list_func_head(fp, false, false);
- if (used != func_hashtab.ht_used || ht_array != func_hashtab.ht_array) {
+ if (changed != func_hashtab.ht_changed) {
emsg(_("E454: function list was modified"));
return;
}
@@ -2730,15 +2730,17 @@ bool function_exists(const char *const name, bool no_deref)
char *get_user_func_name(expand_T *xp, int idx)
{
static size_t done;
+ static int changed;
static hashitem_T *hi;
ufunc_T *fp;
if (idx == 0) {
done = 0;
hi = func_hashtab.ht_array;
+ changed = func_hashtab.ht_changed;
}
assert(hi);
- if (done < func_hashtab.ht_used) {
+ if (changed == func_hashtab.ht_changed && done < func_hashtab.ht_used) {
if (done++ > 0) {
hi++;
}
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index 31dc6f5bd4..fdbfdd7d77 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -223,6 +223,7 @@ int hash_add(hashtab_T *ht, char *key)
void hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash)
{
ht->ht_used++;
+ ht->ht_changed++;
if (hi->hi_key == NULL) {
ht->ht_filled++;
}
@@ -242,6 +243,7 @@ void hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash)
void hash_remove(hashtab_T *ht, hashitem_T *hi)
{
ht->ht_used--;
+ ht->ht_changed++;
hi->hi_key = HI_KEY_REMOVED;
hash_may_resize(ht, 0);
}
@@ -384,6 +386,7 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems)
ht->ht_array = newarray;
ht->ht_mask = newmask;
ht->ht_filled = ht->ht_used;
+ ht->ht_changed++;
}
#define HASH_CYCLE_BODY(hash, p) \
diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h
index 28a3b69d44..0a50fb2ef8 100644
--- a/src/nvim/hashtab.h
+++ b/src/nvim/hashtab.h
@@ -61,14 +61,15 @@ typedef struct hashitem_S {
///
/// The hashtable grows to accommodate more entries when needed.
typedef struct hashtable_S {
- hash_T ht_mask; /// mask used for hash value
- /// (nr of items in array is "ht_mask" + 1)
- size_t ht_used; /// number of items used
- size_t ht_filled; /// number of items used or removed
- int ht_locked; /// counter for hash_lock()
- hashitem_T *ht_array; /// points to the array, allocated when it's
- /// not "ht_smallarray"
- hashitem_T ht_smallarray[HT_INIT_SIZE]; /// initial array
+ hash_T ht_mask; ///< mask used for hash value
+ ///< (nr of items in array is "ht_mask" + 1)
+ size_t ht_used; ///< number of items used
+ size_t ht_filled; ///< number of items used or removed
+ int ht_changed; ///< incremented when adding or removing an item
+ int ht_locked; ///< counter for hash_lock()
+ hashitem_T *ht_array; ///< points to the array, allocated when it's
+ ///< not "ht_smallarray"
+ hashitem_T ht_smallarray[HT_INIT_SIZE]; ///< initial array
} hashtab_T;
/// Iterate over a hashtab