aboutsummaryrefslogtreecommitdiffstats
path: root/st.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2023-10-24 18:33:14 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-11-11 18:49:19 +0900
commit9eac9d71786a8dbec520d0541a91149f01adf8ea (patch)
tree703d4e82d0e2d43c578cf497e6db53631756823c /st.c
parent2a442121d1404f9519d83ac72ac24c58a8389b15 (diff)
downloadruby-9eac9d71786a8dbec520d0541a91149f01adf8ea.tar.gz
[Bug #19969] Compact st_table after deleted if possible
Diffstat (limited to 'st.c')
-rw-r--r--st.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/st.c b/st.c
index 755e230c9a..2825ed1eb6 100644
--- a/st.c
+++ b/st.c
@@ -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