[Bug #19969] Compact st_table after deleted if possible

This commit is contained in:
Nobuyoshi Nakada 2023-10-24 18:33:14 +09:00
parent 2a442121d1
commit 9eac9d7178
No known key found for this signature in database
GPG key ID: 3582D74E1FEE4465
3 changed files with 57 additions and 11 deletions

40
st.c
View file

@ -717,6 +717,8 @@ count_collision(const struct st_hash_type *type)
#error "REBUILD_THRESHOLD should be >= 2"
#endif
static void rebuild_table_with(st_table *new_tab, st_table *tab);
/* Rebuild table TAB. Rebuilding removes all deleted bins and entries
and can change size of the table entries and bins arrays.
Rebuilding is implemented by creation of a new table or by
@ -724,14 +726,6 @@ count_collision(const struct st_hash_type *type)
static void
rebuild_table(st_table *tab)
{
st_index_t i, ni;
unsigned int size_ind;
st_table *new_tab;
st_table_entry *new_entries;
st_table_entry *curr_entry_ptr;
st_index_t *bins;
st_index_t bin_ind;
if ((2 * tab->num_entries <= get_allocated_entries(tab)
&& REBUILD_THRESHOLD * tab->num_entries > get_allocated_entries(tab))
|| tab->num_entries < (1 << MINIMAL_POWER2)) {
@ -739,17 +733,30 @@ rebuild_table(st_table *tab)
tab->num_entries = 0;
if (tab->bins != NULL)
initialize_bins(tab);
new_tab = tab;
new_entries = tab->entries;
rebuild_table_with(tab, tab);
}
else {
st_table *new_tab;
/* This allocation could trigger GC and compaction. If tab is the
* gen_iv_tbl, then tab could have changed in size due to objects being
* freed and/or moved. Do not store attributes of tab before this line. */
new_tab = st_init_table_with_size(tab->type,
2 * tab->num_entries - 1);
new_entries = new_tab->entries;
rebuild_table_with(new_tab, tab);
}
}
static void
rebuild_table_with(st_table *new_tab, st_table *tab)
{
st_index_t i, ni;
unsigned int size_ind;
st_table_entry *new_entries;
st_table_entry *curr_entry_ptr;
st_index_t *bins;
st_index_t bin_ind;
new_entries = new_tab->entries;
ni = 0;
bins = new_tab->bins;
@ -2296,4 +2303,15 @@ rb_st_nth_key(st_table *tab, st_index_t index)
}
}
void
rb_st_compact_table(st_table *tab)
{
st_index_t num = tab->num_entries;
if (REBUILD_THRESHOLD * num <= get_allocated_entries(tab)) {
/* Compaction: */
st_table *new_tab = st_init_table_with_size(tab->type, 2 * num);
rebuild_table_with(new_tab, tab);
}
}
#endif