diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-10-24 18:33:14 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-11-11 18:49:19 +0900 |
commit | 9eac9d71786a8dbec520d0541a91149f01adf8ea (patch) | |
tree | 703d4e82d0e2d43c578cf497e6db53631756823c /st.c | |
parent | 2a442121d1404f9519d83ac72ac24c58a8389b15 (diff) | |
download | ruby-9eac9d71786a8dbec520d0541a91149f01adf8ea.tar.gz |
[Bug #19969] Compact st_table after deleted if possible
Diffstat (limited to 'st.c')
-rw-r--r-- | st.c | 40 |
1 files changed, 29 insertions, 11 deletions
@@ -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 |