summaryrefslogtreecommitdiffstats
path: root/src/hashtab.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-12-26 13:51:26 +0000
committerBram Moolenaar <Bram@vim.org>2022-12-26 13:51:26 +0000
commitd0883faac6a74f777c9a6be9d035c59ee1c969c5 (patch)
tree08c202ace56167b636c1aaf4ebb8121b38b4a7a9 /src/hashtab.c
parent81b7ecc5cb78cad901a9a85e46ecba109cc6ee7d (diff)
patch 9.0.1100: a hashtab with many removed items is not cleaned upv9.0.1100
Problem: A hashtab with many removed items is not cleaned up. Solution: Re-hash a hashtab even when the size didn't change if too many items were removed.
Diffstat (limited to 'src/hashtab.c')
-rw-r--r--src/hashtab.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/src/hashtab.c b/src/hashtab.c
index 8c25c818b2..ddf1877693 100644
--- a/src/hashtab.c
+++ b/src/hashtab.c
@@ -350,7 +350,7 @@ hash_may_resize(
hashitem_T *olditem, *newitem;
unsigned newi;
int todo;
- long_u oldsize, newsize;
+ long_u newsize;
long_u minsize;
long_u newmask;
hash_T perturb;
@@ -366,6 +366,7 @@ hash_may_resize(
emsg("hash_may_resize(): table completely filled");
#endif
+ long_u oldsize = ht->ht_mask + 1;
if (minitems == 0)
{
// Return quickly for small tables with at least two NULL items. NULL
@@ -380,7 +381,6 @@ hash_may_resize(
* Shrink the array when it's less than 1/5 full. When growing it is
* at least 1/4 full (avoids repeated grow-shrink operations)
*/
- oldsize = ht->ht_mask + 1;
if (ht->ht_filled * 3 < oldsize * 2 && ht->ht_used > oldsize / 5)
return OK;
@@ -422,9 +422,10 @@ hash_may_resize(
CLEAR_FIELD(ht->ht_smallarray);
}
- else if (newsize == ht->ht_mask + 1)
+ else if (newsize == oldsize && ht->ht_filled * 3 < oldsize * 2)
{
- // the hashtab is already at the desired size, bail out
+ // The hashtab is already at the desired size, and there are not too
+ // many removed items, bail out.
return OK;
}