diff options
| author | Jean Boussier <jean.boussier@gmail.com> | 2026-01-30 09:41:27 +0100 |
|---|---|---|
| committer | Jean Boussier <jean.boussier@gmail.com> | 2026-01-30 14:48:37 +0100 |
| commit | 3c100019a4a1b0ef66db76ec3b14f63eac51dd4d (patch) | |
| tree | a04dfe22bf18c185d8a50a19018db740412815c3 | |
| parent | dddb6511184e24413618645af9ed1ea7e8ae06ac (diff) | |
st.c: Use ruby_sized_xfree
Followup: https://github.com/ruby/ruby/pull/15989
This feeds the GC with useful allocation metrics, but also ensure
we're correctly keeping track of our allocation sizes which is
beneficial for safety.
It also allows to use C23's `free_sized`.
| -rw-r--r-- | depend | 34 | ||||
| -rw-r--r-- | st.c | 103 |
2 files changed, 106 insertions, 31 deletions
@@ -16298,16 +16298,28 @@ sprintf.$(OBJEXT): {$(VPATH)}st.h sprintf.$(OBJEXT): {$(VPATH)}subst.h sprintf.$(OBJEXT): {$(VPATH)}util.h sprintf.$(OBJEXT): {$(VPATH)}vsnprintf.c +st.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +st.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +st.$(OBJEXT): $(CCAN_DIR)/list/list.h +st.$(OBJEXT): $(CCAN_DIR)/str/str.h st.$(OBJEXT): $(hdrdir)/ruby/ruby.h +st.$(OBJEXT): $(top_srcdir)/internal/array.h +st.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h st.$(OBJEXT): $(top_srcdir)/internal/bits.h +st.$(OBJEXT): $(top_srcdir)/internal/box.h st.$(OBJEXT): $(top_srcdir)/internal/compilers.h +st.$(OBJEXT): $(top_srcdir)/internal/gc.h st.$(OBJEXT): $(top_srcdir)/internal/hash.h +st.$(OBJEXT): $(top_srcdir)/internal/imemo.h st.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +st.$(OBJEXT): $(top_srcdir)/internal/serial.h st.$(OBJEXT): $(top_srcdir)/internal/set_table.h st.$(OBJEXT): $(top_srcdir)/internal/st.h st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +st.$(OBJEXT): $(top_srcdir)/internal/vm.h st.$(OBJEXT): $(top_srcdir)/internal/warnings.h st.$(OBJEXT): {$(VPATH)}assert.h +st.$(OBJEXT): {$(VPATH)}atomic.h st.$(OBJEXT): {$(VPATH)}backward/2/assume.h st.$(OBJEXT): {$(VPATH)}backward/2/attributes.h st.$(OBJEXT): {$(VPATH)}backward/2/bool.h @@ -16319,6 +16331,9 @@ st.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h st.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h st.$(OBJEXT): {$(VPATH)}config.h st.$(OBJEXT): {$(VPATH)}defines.h +st.$(OBJEXT): {$(VPATH)}encoding.h +st.$(OBJEXT): {$(VPATH)}id.h +st.$(OBJEXT): {$(VPATH)}id_table.h st.$(OBJEXT): {$(VPATH)}intern.h st.$(OBJEXT): {$(VPATH)}internal.h st.$(OBJEXT): {$(VPATH)}internal/abi.h @@ -16392,6 +16407,15 @@ st.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h st.$(OBJEXT): {$(VPATH)}internal/ctype.h st.$(OBJEXT): {$(VPATH)}internal/dllexport.h st.$(OBJEXT): {$(VPATH)}internal/dosish.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +st.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h st.$(OBJEXT): {$(VPATH)}internal/error.h st.$(OBJEXT): {$(VPATH)}internal/eval.h st.$(OBJEXT): {$(VPATH)}internal/event.h @@ -16463,11 +16487,21 @@ st.$(OBJEXT): {$(VPATH)}internal/value_type.h st.$(OBJEXT): {$(VPATH)}internal/variable.h st.$(OBJEXT): {$(VPATH)}internal/warning_push.h st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +st.$(OBJEXT): {$(VPATH)}method.h st.$(OBJEXT): {$(VPATH)}missing.h +st.$(OBJEXT): {$(VPATH)}node.h +st.$(OBJEXT): {$(VPATH)}onigmo.h +st.$(OBJEXT): {$(VPATH)}oniguruma.h st.$(OBJEXT): {$(VPATH)}ruby_assert.h +st.$(OBJEXT): {$(VPATH)}ruby_atomic.h +st.$(OBJEXT): {$(VPATH)}rubyparser.h st.$(OBJEXT): {$(VPATH)}st.c st.$(OBJEXT): {$(VPATH)}st.h st.$(OBJEXT): {$(VPATH)}subst.h +st.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +st.$(OBJEXT): {$(VPATH)}thread_native.h +st.$(OBJEXT): {$(VPATH)}vm_core.h +st.$(OBJEXT): {$(VPATH)}vm_opts.h strftime.$(OBJEXT): $(hdrdir)/ruby/ruby.h strftime.$(OBJEXT): $(top_srcdir)/internal/compilers.h strftime.$(OBJEXT): $(top_srcdir)/internal/encoding.h @@ -107,6 +107,7 @@ #elif defined RUBY_EXPORT #include "internal.h" #include "internal/bits.h" +#include "internal/gc.h" #include "internal/hash.h" #include "internal/sanitizers.h" #include "internal/set_table.h" @@ -173,7 +174,14 @@ static const struct st_hash_type type_strcasehash = { #define malloc ruby_xmalloc #define calloc ruby_xcalloc #define realloc ruby_xrealloc +#define sized_realloc ruby_sized_xrealloc #define free ruby_xfree +#define sized_free ruby_sized_xfree +#define free_fixed_ptr(v) ruby_sized_xfree((v), sizeof(*(v))) +#else +#define sized_realloc(ptr, new_size, old_size) realloc(ptr, new_size) +#define sized_free(v, s) free(v) +#define free_fixed_ptr(v) free(v) #endif #define EQUAL(tab,x,y) ((x) == (y) || (*(tab)->type->compare)((x),(y)) == 0) @@ -551,7 +559,7 @@ st_init_existing_table_with_size(st_table *tab, const struct st_hash_type *type, tab->bins = (st_index_t *) malloc(bins_size(tab)); #ifndef RUBY if (tab->bins == NULL) { - free(tab); + free_fixed_ptr(tab); return NULL; } #endif @@ -585,7 +593,7 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size) st_init_existing_table_with_size(tab, type, size); #else if (st_init_existing_table_with_size(tab, type, size) == NULL) { - free(tab); + free_fixed_ptr(tab); return NULL; } #endif @@ -661,13 +669,36 @@ st_clear(st_table *tab) tab->rebuilds_num++; } +static inline size_t +st_entries_memsize(const st_table *tab) +{ + return get_allocated_entries(tab) * sizeof(st_table_entry); +} + +static inline size_t +st_bins_memsize(const st_table *tab) +{ + return tab->bins == NULL ? 0 : bins_size(tab); +} + +static inline void +st_free_entries(const st_table *tab) +{ + sized_free(tab->entries, st_entries_memsize(tab)); +} + +static inline void +st_free_bins(const st_table *tab) +{ + sized_free(tab->bins, st_bins_memsize(tab)); +} /* Free table TAB space. */ void st_free_table(st_table *tab) { - free(tab->bins); - free(tab->entries); - free(tab); + st_free_bins(tab); + st_free_entries(tab); + free_fixed_ptr(tab); } /* Return byte size of memory allocated for table TAB. */ @@ -676,8 +707,8 @@ st_memsize(const st_table *tab) { RUBY_ASSERT(tab != NULL); return(sizeof(st_table) - + (tab->bins == NULL ? 0 : bins_size(tab)) - + get_allocated_entries(tab) * sizeof(st_table_entry)); + + st_bins_memsize(tab) + + st_entries_memsize(tab)); } static st_index_t @@ -799,14 +830,15 @@ rebuild_table_with(st_table *const new_tab, st_table *const tab) static void rebuild_move_table(st_table *const new_tab, st_table *const tab) { + st_free_bins(tab); + st_free_entries(tab); + tab->entry_power = new_tab->entry_power; tab->bin_power = new_tab->bin_power; tab->size_ind = new_tab->size_ind; - free(tab->bins); tab->bins = new_tab->bins; - free(tab->entries); tab->entries = new_tab->entries; - free(new_tab); + free_fixed_ptr(new_tab); } static void @@ -2135,16 +2167,17 @@ st_expand_table(st_table *tab, st_index_t siz) tmp = st_init_table_with_size(tab->type, siz); n = get_allocated_entries(tab); MEMCPY(tmp->entries, tab->entries, st_table_entry, n); - free(tab->entries); - free(tab->bins); - free(tmp->bins); + st_free_bins(tab); + st_free_entries(tab); + st_free_bins(tmp); + tab->entry_power = tmp->entry_power; tab->bin_power = tmp->bin_power; tab->size_ind = tmp->size_ind; tab->entries = tmp->entries; tab->bins = NULL; tab->rebuilds_num++; - free(tmp); + free_fixed_ptr(tmp); } /* Rehash using linear search. Return TRUE if we found that the table @@ -2156,7 +2189,7 @@ st_rehash_linear(st_table *tab) st_index_t i, j; st_table_entry *p, *q; - free(tab->bins); + st_free_bins(tab); tab->bins = NULL; for (i = tab->entries_start; i < tab->entries_bound; i++) { @@ -2188,10 +2221,11 @@ st_rehash_indexed(st_table *tab) { int eq_p, rebuilt_p; st_index_t i; - st_index_t const n = bins_size(tab); + + if (!tab->bins) { + tab->bins = malloc(bins_size(tab)); + } unsigned int const size_ind = get_size_ind(tab); - st_index_t *bins = realloc(tab->bins, n); - tab->bins = bins; initialize_bins(tab); for (i = tab->entries_start; i < tab->entries_bound; i++) { st_table_entry *p = &tab->entries[i]; @@ -2207,10 +2241,10 @@ st_rehash_indexed(st_table *tab) ind = hash_bin(p->hash, tab); for (;;) { - st_index_t bin = get_bin(bins, size_ind, ind); + st_index_t bin = get_bin(tab->bins, size_ind, ind); if (EMPTY_OR_DELETED_BIN_P(bin)) { /* ok, new room */ - set_bin(bins, size_ind, ind, i + ENTRY_BASE); + set_bin(tab->bins, size_ind, ind, i + ENTRY_BASE); break; } else { @@ -2446,6 +2480,16 @@ set_make_tab_empty(set_table *tab) set_initialize_bins(tab); } +static inline size_t +set_entries_memsize(set_table *tab) +{ + size_t memsize = set_get_allocated_entries(tab) * sizeof(set_table_entry); + if (set_has_bins(tab)) { + memsize += set_bins_size(tab); + } + return memsize; +} + static set_table * set_init_existing_table_with_size(set_table *tab, const struct st_hash_type *type, st_index_t size) { @@ -2471,12 +2515,7 @@ set_init_existing_table_with_size(set_table *tab, const struct st_hash_type *typ tab->bin_power = features[n].bin_power; tab->size_ind = features[n].size_ind; - size_t memsize = 0; - if (set_has_bins(tab)) { - memsize += set_bins_size(tab); - } - memsize += set_get_allocated_entries(tab) * sizeof(set_table_entry); - tab->entries = (set_table_entry *)malloc(memsize); + tab->entries = (set_table_entry *)malloc(set_entries_memsize(tab)); set_make_tab_empty(tab); tab->rebuilds_num = 0; return tab; @@ -2526,8 +2565,8 @@ set_table_clear(set_table *tab) void set_free_table(set_table *tab) { - free(tab->entries); - free(tab); + sized_free(tab->entries, set_entries_memsize(tab)); + free_fixed_ptr(tab); } /* Return byte size of memory allocated for table TAB. */ @@ -2625,12 +2664,14 @@ set_rebuild_table_with(set_table *const new_tab, set_table *const tab) static void set_rebuild_move_table(set_table *const new_tab, set_table *const tab) { + sized_free(tab->entries, set_entries_memsize(tab)); + tab->entries = new_tab->entries; + tab->entry_power = new_tab->entry_power; tab->bin_power = new_tab->bin_power; tab->size_ind = new_tab->size_ind; - free(tab->entries); - tab->entries = new_tab->entries; - free(new_tab); + + free_fixed_ptr(new_tab); } static void |
