Skip to content

Commit 3c10001

Browse files
committed
st.c: Use ruby_sized_xfree
Followup: ruby#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`.
1 parent dddb651 commit 3c10001

File tree

2 files changed

+106
-31
lines changed

2 files changed

+106
-31
lines changed

depend

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16298,16 +16298,28 @@ sprintf.$(OBJEXT): {$(VPATH)}st.h
1629816298
sprintf.$(OBJEXT): {$(VPATH)}subst.h
1629916299
sprintf.$(OBJEXT): {$(VPATH)}util.h
1630016300
sprintf.$(OBJEXT): {$(VPATH)}vsnprintf.c
16301+
st.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
16302+
st.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
16303+
st.$(OBJEXT): $(CCAN_DIR)/list/list.h
16304+
st.$(OBJEXT): $(CCAN_DIR)/str/str.h
1630116305
st.$(OBJEXT): $(hdrdir)/ruby/ruby.h
16306+
st.$(OBJEXT): $(top_srcdir)/internal/array.h
16307+
st.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
1630216308
st.$(OBJEXT): $(top_srcdir)/internal/bits.h
16309+
st.$(OBJEXT): $(top_srcdir)/internal/box.h
1630316310
st.$(OBJEXT): $(top_srcdir)/internal/compilers.h
16311+
st.$(OBJEXT): $(top_srcdir)/internal/gc.h
1630416312
st.$(OBJEXT): $(top_srcdir)/internal/hash.h
16313+
st.$(OBJEXT): $(top_srcdir)/internal/imemo.h
1630516314
st.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
16315+
st.$(OBJEXT): $(top_srcdir)/internal/serial.h
1630616316
st.$(OBJEXT): $(top_srcdir)/internal/set_table.h
1630716317
st.$(OBJEXT): $(top_srcdir)/internal/st.h
1630816318
st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
16319+
st.$(OBJEXT): $(top_srcdir)/internal/vm.h
1630916320
st.$(OBJEXT): $(top_srcdir)/internal/warnings.h
1631016321
st.$(OBJEXT): {$(VPATH)}assert.h
16322+
st.$(OBJEXT): {$(VPATH)}atomic.h
1631116323
st.$(OBJEXT): {$(VPATH)}backward/2/assume.h
1631216324
st.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
1631316325
st.$(OBJEXT): {$(VPATH)}backward/2/bool.h
@@ -16319,6 +16331,9 @@ st.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
1631916331
st.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
1632016332
st.$(OBJEXT): {$(VPATH)}config.h
1632116333
st.$(OBJEXT): {$(VPATH)}defines.h
16334+
st.$(OBJEXT): {$(VPATH)}encoding.h
16335+
st.$(OBJEXT): {$(VPATH)}id.h
16336+
st.$(OBJEXT): {$(VPATH)}id_table.h
1632216337
st.$(OBJEXT): {$(VPATH)}intern.h
1632316338
st.$(OBJEXT): {$(VPATH)}internal.h
1632416339
st.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -16392,6 +16407,15 @@ st.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
1639216407
st.$(OBJEXT): {$(VPATH)}internal/ctype.h
1639316408
st.$(OBJEXT): {$(VPATH)}internal/dllexport.h
1639416409
st.$(OBJEXT): {$(VPATH)}internal/dosish.h
16410+
st.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
16411+
st.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
16412+
st.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
16413+
st.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
16414+
st.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
16415+
st.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
16416+
st.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
16417+
st.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
16418+
st.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
1639516419
st.$(OBJEXT): {$(VPATH)}internal/error.h
1639616420
st.$(OBJEXT): {$(VPATH)}internal/eval.h
1639716421
st.$(OBJEXT): {$(VPATH)}internal/event.h
@@ -16463,11 +16487,21 @@ st.$(OBJEXT): {$(VPATH)}internal/value_type.h
1646316487
st.$(OBJEXT): {$(VPATH)}internal/variable.h
1646416488
st.$(OBJEXT): {$(VPATH)}internal/warning_push.h
1646516489
st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
16490+
st.$(OBJEXT): {$(VPATH)}method.h
1646616491
st.$(OBJEXT): {$(VPATH)}missing.h
16492+
st.$(OBJEXT): {$(VPATH)}node.h
16493+
st.$(OBJEXT): {$(VPATH)}onigmo.h
16494+
st.$(OBJEXT): {$(VPATH)}oniguruma.h
1646716495
st.$(OBJEXT): {$(VPATH)}ruby_assert.h
16496+
st.$(OBJEXT): {$(VPATH)}ruby_atomic.h
16497+
st.$(OBJEXT): {$(VPATH)}rubyparser.h
1646816498
st.$(OBJEXT): {$(VPATH)}st.c
1646916499
st.$(OBJEXT): {$(VPATH)}st.h
1647016500
st.$(OBJEXT): {$(VPATH)}subst.h
16501+
st.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
16502+
st.$(OBJEXT): {$(VPATH)}thread_native.h
16503+
st.$(OBJEXT): {$(VPATH)}vm_core.h
16504+
st.$(OBJEXT): {$(VPATH)}vm_opts.h
1647116505
strftime.$(OBJEXT): $(hdrdir)/ruby/ruby.h
1647216506
strftime.$(OBJEXT): $(top_srcdir)/internal/compilers.h
1647316507
strftime.$(OBJEXT): $(top_srcdir)/internal/encoding.h

st.c

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
#elif defined RUBY_EXPORT
108108
#include "internal.h"
109109
#include "internal/bits.h"
110+
#include "internal/gc.h"
110111
#include "internal/hash.h"
111112
#include "internal/sanitizers.h"
112113
#include "internal/set_table.h"
@@ -173,7 +174,14 @@ static const struct st_hash_type type_strcasehash = {
173174
#define malloc ruby_xmalloc
174175
#define calloc ruby_xcalloc
175176
#define realloc ruby_xrealloc
177+
#define sized_realloc ruby_sized_xrealloc
176178
#define free ruby_xfree
179+
#define sized_free ruby_sized_xfree
180+
#define free_fixed_ptr(v) ruby_sized_xfree((v), sizeof(*(v)))
181+
#else
182+
#define sized_realloc(ptr, new_size, old_size) realloc(ptr, new_size)
183+
#define sized_free(v, s) free(v)
184+
#define free_fixed_ptr(v) free(v)
177185
#endif
178186

179187
#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,
551559
tab->bins = (st_index_t *) malloc(bins_size(tab));
552560
#ifndef RUBY
553561
if (tab->bins == NULL) {
554-
free(tab);
562+
free_fixed_ptr(tab);
555563
return NULL;
556564
}
557565
#endif
@@ -585,7 +593,7 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
585593
st_init_existing_table_with_size(tab, type, size);
586594
#else
587595
if (st_init_existing_table_with_size(tab, type, size) == NULL) {
588-
free(tab);
596+
free_fixed_ptr(tab);
589597
return NULL;
590598
}
591599
#endif
@@ -661,13 +669,36 @@ st_clear(st_table *tab)
661669
tab->rebuilds_num++;
662670
}
663671

672+
static inline size_t
673+
st_entries_memsize(const st_table *tab)
674+
{
675+
return get_allocated_entries(tab) * sizeof(st_table_entry);
676+
}
677+
678+
static inline size_t
679+
st_bins_memsize(const st_table *tab)
680+
{
681+
return tab->bins == NULL ? 0 : bins_size(tab);
682+
}
683+
684+
static inline void
685+
st_free_entries(const st_table *tab)
686+
{
687+
sized_free(tab->entries, st_entries_memsize(tab));
688+
}
689+
690+
static inline void
691+
st_free_bins(const st_table *tab)
692+
{
693+
sized_free(tab->bins, st_bins_memsize(tab));
694+
}
664695
/* Free table TAB space. */
665696
void
666697
st_free_table(st_table *tab)
667698
{
668-
free(tab->bins);
669-
free(tab->entries);
670-
free(tab);
699+
st_free_bins(tab);
700+
st_free_entries(tab);
701+
free_fixed_ptr(tab);
671702
}
672703

673704
/* Return byte size of memory allocated for table TAB. */
@@ -676,8 +707,8 @@ st_memsize(const st_table *tab)
676707
{
677708
RUBY_ASSERT(tab != NULL);
678709
return(sizeof(st_table)
679-
+ (tab->bins == NULL ? 0 : bins_size(tab))
680-
+ get_allocated_entries(tab) * sizeof(st_table_entry));
710+
+ st_bins_memsize(tab)
711+
+ st_entries_memsize(tab));
681712
}
682713

683714
static st_index_t
@@ -799,14 +830,15 @@ rebuild_table_with(st_table *const new_tab, st_table *const tab)
799830
static void
800831
rebuild_move_table(st_table *const new_tab, st_table *const tab)
801832
{
833+
st_free_bins(tab);
834+
st_free_entries(tab);
835+
802836
tab->entry_power = new_tab->entry_power;
803837
tab->bin_power = new_tab->bin_power;
804838
tab->size_ind = new_tab->size_ind;
805-
free(tab->bins);
806839
tab->bins = new_tab->bins;
807-
free(tab->entries);
808840
tab->entries = new_tab->entries;
809-
free(new_tab);
841+
free_fixed_ptr(new_tab);
810842
}
811843

812844
static void
@@ -2135,16 +2167,17 @@ st_expand_table(st_table *tab, st_index_t siz)
21352167
tmp = st_init_table_with_size(tab->type, siz);
21362168
n = get_allocated_entries(tab);
21372169
MEMCPY(tmp->entries, tab->entries, st_table_entry, n);
2138-
free(tab->entries);
2139-
free(tab->bins);
2140-
free(tmp->bins);
2170+
st_free_bins(tab);
2171+
st_free_entries(tab);
2172+
st_free_bins(tmp);
2173+
21412174
tab->entry_power = tmp->entry_power;
21422175
tab->bin_power = tmp->bin_power;
21432176
tab->size_ind = tmp->size_ind;
21442177
tab->entries = tmp->entries;
21452178
tab->bins = NULL;
21462179
tab->rebuilds_num++;
2147-
free(tmp);
2180+
free_fixed_ptr(tmp);
21482181
}
21492182

21502183
/* Rehash using linear search. Return TRUE if we found that the table
@@ -2156,7 +2189,7 @@ st_rehash_linear(st_table *tab)
21562189
st_index_t i, j;
21572190
st_table_entry *p, *q;
21582191

2159-
free(tab->bins);
2192+
st_free_bins(tab);
21602193
tab->bins = NULL;
21612194

21622195
for (i = tab->entries_start; i < tab->entries_bound; i++) {
@@ -2188,10 +2221,11 @@ st_rehash_indexed(st_table *tab)
21882221
{
21892222
int eq_p, rebuilt_p;
21902223
st_index_t i;
2191-
st_index_t const n = bins_size(tab);
2224+
2225+
if (!tab->bins) {
2226+
tab->bins = malloc(bins_size(tab));
2227+
}
21922228
unsigned int const size_ind = get_size_ind(tab);
2193-
st_index_t *bins = realloc(tab->bins, n);
2194-
tab->bins = bins;
21952229
initialize_bins(tab);
21962230
for (i = tab->entries_start; i < tab->entries_bound; i++) {
21972231
st_table_entry *p = &tab->entries[i];
@@ -2207,10 +2241,10 @@ st_rehash_indexed(st_table *tab)
22072241

22082242
ind = hash_bin(p->hash, tab);
22092243
for (;;) {
2210-
st_index_t bin = get_bin(bins, size_ind, ind);
2244+
st_index_t bin = get_bin(tab->bins, size_ind, ind);
22112245
if (EMPTY_OR_DELETED_BIN_P(bin)) {
22122246
/* ok, new room */
2213-
set_bin(bins, size_ind, ind, i + ENTRY_BASE);
2247+
set_bin(tab->bins, size_ind, ind, i + ENTRY_BASE);
22142248
break;
22152249
}
22162250
else {
@@ -2446,6 +2480,16 @@ set_make_tab_empty(set_table *tab)
24462480
set_initialize_bins(tab);
24472481
}
24482482

2483+
static inline size_t
2484+
set_entries_memsize(set_table *tab)
2485+
{
2486+
size_t memsize = set_get_allocated_entries(tab) * sizeof(set_table_entry);
2487+
if (set_has_bins(tab)) {
2488+
memsize += set_bins_size(tab);
2489+
}
2490+
return memsize;
2491+
}
2492+
24492493
static set_table *
24502494
set_init_existing_table_with_size(set_table *tab, const struct st_hash_type *type, st_index_t size)
24512495
{
@@ -2471,12 +2515,7 @@ set_init_existing_table_with_size(set_table *tab, const struct st_hash_type *typ
24712515
tab->bin_power = features[n].bin_power;
24722516
tab->size_ind = features[n].size_ind;
24732517

2474-
size_t memsize = 0;
2475-
if (set_has_bins(tab)) {
2476-
memsize += set_bins_size(tab);
2477-
}
2478-
memsize += set_get_allocated_entries(tab) * sizeof(set_table_entry);
2479-
tab->entries = (set_table_entry *)malloc(memsize);
2518+
tab->entries = (set_table_entry *)malloc(set_entries_memsize(tab));
24802519
set_make_tab_empty(tab);
24812520
tab->rebuilds_num = 0;
24822521
return tab;
@@ -2526,8 +2565,8 @@ set_table_clear(set_table *tab)
25262565
void
25272566
set_free_table(set_table *tab)
25282567
{
2529-
free(tab->entries);
2530-
free(tab);
2568+
sized_free(tab->entries, set_entries_memsize(tab));
2569+
free_fixed_ptr(tab);
25312570
}
25322571

25332572
/* 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)
26252664
static void
26262665
set_rebuild_move_table(set_table *const new_tab, set_table *const tab)
26272666
{
2667+
sized_free(tab->entries, set_entries_memsize(tab));
2668+
tab->entries = new_tab->entries;
2669+
26282670
tab->entry_power = new_tab->entry_power;
26292671
tab->bin_power = new_tab->bin_power;
26302672
tab->size_ind = new_tab->size_ind;
2631-
free(tab->entries);
2632-
tab->entries = new_tab->entries;
2633-
free(new_tab);
2673+
2674+
free_fixed_ptr(new_tab);
26342675
}
26352676

26362677
static void

0 commit comments

Comments
 (0)