Skip to content

Commit 48ddbab

Browse files
committed
Use st_table for managed table instead of id_table
Add managed_st_table functions and use them in transcode.c.
1 parent 34f0766 commit 48ddbab

File tree

3 files changed

+145
-42
lines changed

3 files changed

+145
-42
lines changed

include/ruby/st.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@ CONSTFUNC(st_index_t rb_st_hash_start(st_index_t h));
187187

188188
void rb_hash_bulk_insert_into_st_table(long, const VALUE *, VALUE);
189189

190+
VALUE rb_managed_st_table_create_numtable(size_t capa);
191+
VALUE rb_managed_st_table_create_strtable(size_t capa);
192+
VALUE rb_managed_st_table_create_strcasetable(size_t capa);
193+
int rb_managed_st_table_lookup(VALUE tbl, st_data_t key, st_data_t *value);
194+
int rb_managed_st_table_insert(VALUE tbl, st_data_t key, st_data_t value);
195+
void rb_managed_st_table_add_direct(VALUE tbl, st_data_t key, st_data_t value);
196+
VALUE rb_managed_st_table_dup(VALUE old_table);
197+
190198
RUBY_SYMBOL_EXPORT_END
191199

192200
#if defined(__cplusplus)

st.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3206,4 +3206,106 @@ set_compact_table(set_table *tab)
32063206
}
32073207
}
32083208

3209+
static void
3210+
managed_st_table_free(void *data)
3211+
{
3212+
st_table *tbl = (st_table *)data;
3213+
free(tbl->bins);
3214+
free(tbl->entries);
3215+
}
3216+
3217+
static size_t
3218+
managed_st_table_memsize(const void *data)
3219+
{
3220+
st_table *tbl = (st_table*)data;
3221+
return st_memsize(tbl) - sizeof(st_table);
3222+
}
3223+
3224+
const rb_data_type_t rb_managed_st_table_type = {
3225+
.wrap_struct_name = "VM/managed_st_table",
3226+
.function = {
3227+
.dmark = NULL, // Nothing to mark
3228+
.dfree = (RUBY_DATA_FUNC)managed_st_table_free,
3229+
.dsize = managed_st_table_memsize,
3230+
},
3231+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE,
3232+
};
3233+
3234+
static inline st_table *
3235+
managed_st_table_ptr(VALUE obj)
3236+
{
3237+
RUBY_ASSERT(RB_TYPE_P(obj, T_DATA));
3238+
RUBY_ASSERT(rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), &rb_managed_st_table_type));
3239+
3240+
return RTYPEDDATA_GET_DATA(obj);
3241+
}
3242+
3243+
static VALUE
3244+
rb_managed_st_table_create_type(const rb_data_type_t *type, const struct st_hash_type *table_type, size_t capa)
3245+
{
3246+
struct st_table *tbl;
3247+
VALUE obj = TypedData_Make_Struct(0, struct st_table, type, tbl);
3248+
st_init_existing_table_with_size(tbl, table_type, capa);
3249+
return obj;
3250+
}
3251+
3252+
VALUE
3253+
rb_managed_st_table_create_numtable(size_t capa)
3254+
{
3255+
return rb_managed_st_table_create_type(&rb_managed_st_table_type, &type_numhash, capa);
3256+
}
3257+
3258+
VALUE
3259+
rb_managed_st_table_create_strtable(size_t capa)
3260+
{
3261+
return rb_managed_st_table_create_type(&rb_managed_st_table_type, &type_strhash, capa);
3262+
}
3263+
3264+
VALUE
3265+
rb_managed_st_table_create_strcasetable(size_t capa)
3266+
{
3267+
return rb_managed_st_table_create_type(&rb_managed_st_table_type, &type_strcasehash, capa);
3268+
}
3269+
3270+
int
3271+
rb_managed_st_table_lookup(VALUE tbl, st_data_t key, VALUE *value)
3272+
{
3273+
st_table *st = managed_st_table_ptr(tbl);
3274+
st_data_t *val = (st_data_t*)value;
3275+
return st_lookup(st, key, val);
3276+
}
3277+
3278+
int
3279+
rb_managed_st_table_insert(VALUE tbl, st_data_t key, VALUE value)
3280+
{
3281+
st_table *st = managed_st_table_ptr(tbl);
3282+
return st_insert(st, key, (st_data_t)value);
3283+
}
3284+
3285+
void
3286+
rb_managed_st_table_add_direct(VALUE tbl, st_data_t key, st_data_t value)
3287+
{
3288+
st_table *st = managed_st_table_ptr(tbl);
3289+
return st_add_direct(st, key, value);
3290+
}
3291+
3292+
static int
3293+
managed_st_table_dup_i(st_data_t key, st_data_t val, st_data_t data) {
3294+
st_table *tbl = (st_table *)data;
3295+
st_insert(tbl, key, val);
3296+
return ST_CONTINUE;
3297+
}
3298+
3299+
VALUE
3300+
rb_managed_st_table_dup(VALUE old_table)
3301+
{
3302+
struct st_table *new_tbl;
3303+
VALUE obj = TypedData_Make_Struct(0, struct st_table, RTYPEDDATA_TYPE(old_table), new_tbl);
3304+
struct st_table *old_tbl = managed_st_table_ptr(old_table);
3305+
st_init_existing_table_with_size(new_tbl, old_tbl->type, old_tbl->num_entries+1);
3306+
st_foreach(old_tbl, managed_st_table_dup_i, (st_data_t)new_tbl);
3307+
3308+
return obj;
3309+
}
3310+
32093311
#endif

transcode.c

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,32 @@ make_transcoder_entry(const char *sname, const char *dname)
232232
st_table *table2;
233233
transcoder_entry_t *entry = NULL;
234234

235+
char key_buf[SRC_ENC_TO_DST_ENC_KEY_SIZE] = { 0 };
236+
char *key = NULL;
237+
gen_src_to_dst_encodings_key(key_buf, sname, dname);
238+
while (1) {
239+
VALUE tbl = fast_transcoder_entry_table;
240+
VALUE entry_got;
241+
if (rb_managed_st_table_lookup(tbl, (st_data_t)key_buf, &entry_got)) {
242+
entry = (transcoder_entry_t*)entry_got;
243+
break;
244+
} else {
245+
if (!entry) {
246+
entry = ALLOC(transcoder_entry_t);
247+
entry->sname = sname;
248+
entry->dname = dname;
249+
entry->lib = NULL;
250+
entry->transcoder = NULL;
251+
}
252+
VALUE new_tbl = rb_managed_st_table_dup(tbl);
253+
if (!key) key = strdup(key_buf);
254+
rb_managed_st_table_insert(new_tbl, (st_data_t)key, (VALUE)entry);
255+
if (RUBY_ATOMIC_VALUE_CAS(fast_transcoder_entry_table, tbl, new_tbl) == tbl) {
256+
break;
257+
}
258+
}
259+
}
260+
235261
// TODO: we should be able to remove this table soon
236262
RB_VM_LOCKING() {
237263
if (!st_lookup(transcoder_table, (st_data_t)sname, &val)) {
@@ -240,58 +266,25 @@ make_transcoder_entry(const char *sname, const char *dname)
240266
}
241267
table2 = (st_table *)val;
242268
if (!st_lookup(table2, (st_data_t)dname, &val)) {
243-
entry = ALLOC(transcoder_entry_t);
244-
entry->sname = sname;
245-
entry->dname = dname;
246-
entry->lib = NULL;
247-
entry->transcoder = NULL;
248269
val = (st_data_t)entry;
249270
st_add_direct(table2, (st_data_t)dname, val);
250271
} else {
251272
entry = (transcoder_entry_t*)val;
252273
}
253274
}
254-
char key_buf[SRC_ENC_TO_DST_ENC_KEY_SIZE] = { 0 };
255-
gen_src_to_dst_encodings_key(key_buf, sname, dname);
256-
ID key = rb_intern(key_buf);
257-
while (1) {
258-
VALUE tbl = fast_transcoder_entry_table;
259-
VALUE entry_got;
260-
if (rb_managed_id_table_lookup(tbl, key, &entry_got)) {
261-
break;
262-
} else {
263-
VALUE new_tbl = rb_managed_id_table_dup(tbl);
264-
rb_managed_id_table_insert(new_tbl, key, (VALUE)entry);
265-
if (RUBY_ATOMIC_VALUE_CAS(fast_transcoder_entry_table, tbl, new_tbl) == tbl) {
266-
break;
267-
}
268-
}
269-
}
270275
return entry;
271276
}
272277

273278
static transcoder_entry_t *
274279
get_transcoder_entry(const char *sname, const char *dname)
275280
{
276-
st_data_t val = 0;
277-
st_table *table2;
278281
char key_buf[SRC_ENC_TO_DST_ENC_KEY_SIZE] = { 0 };
279282
gen_src_to_dst_encodings_key(key_buf, sname, dname);
280283
VALUE entry_val;
281-
if (rb_managed_id_table_lookup(fast_transcoder_entry_table, rb_intern(key_buf), &entry_val)) {
284+
if (rb_managed_st_table_lookup(fast_transcoder_entry_table, (st_data_t)key_buf, &entry_val)) {
282285
return (transcoder_entry_t*)entry_val;
283286
}
284-
285-
// TODO: we should be able to remove this table soon
286-
RB_VM_LOCKING() {
287-
if (st_lookup(transcoder_table, (st_data_t)sname, &val)) {
288-
table2 = (st_table *)val;
289-
if (!st_lookup(table2, (st_data_t)dname, &val)) {
290-
val = 0;
291-
}
292-
}
293-
}
294-
return (transcoder_entry_t *)val;
287+
return NULL;
295288
}
296289

297290
void
@@ -1095,11 +1088,11 @@ rb_econv_open0(rb_encoding *senc, const char *sname, rb_encoding *denc, const ch
10951088
toarg.entries = NULL;
10961089
toarg.num_additional = 0;
10971090
char key_buf[SRC_ENC_TO_DST_ENC_KEY_SIZE] = { 0 };
1091+
char *key;
10981092
gen_src_to_dst_encodings_key(key_buf, sname, dname);
1099-
ID src_to_dest_id = rb_intern(key_buf);
11001093
VALUE managed_val;
11011094
VALUE tbl = RUBY_ATOMIC_VALUE_LOAD(fast_transcoder_path_table);
1102-
if (rb_managed_id_table_lookup(tbl, src_to_dest_id, &managed_val)) {
1095+
if (rb_managed_st_table_lookup(tbl, (st_data_t)key_buf, &managed_val)) {
11031096
entries = (transcoder_entry_t **)managed_val;
11041097
} else {
11051098
num_trans = transcode_search_path(sname, dname, trans_open_i, (void *)&toarg);
@@ -1111,8 +1104,9 @@ rb_econv_open0(rb_encoding *senc, const char *sname, rb_encoding *denc, const ch
11111104
// No need for CAS loop if it's not most recent `fast_transcoder_table`, some values
11121105
// can be lost. It will just go through the slow path next time for the lost src/dst encoding
11131106
// pairs
1114-
VALUE new_tbl = rb_managed_id_table_dup(tbl);
1115-
rb_managed_id_table_insert(new_tbl, src_to_dest_id, (VALUE)entries);
1107+
VALUE new_tbl = rb_managed_st_table_dup(tbl);
1108+
key = strdup(key_buf);
1109+
rb_managed_st_table_insert(new_tbl, (st_data_t)key, (VALUE)entries);
11161110
RUBY_ATOMIC_VALUE_SET(fast_transcoder_path_table, new_tbl);
11171111
}
11181112
}
@@ -1919,7 +1913,6 @@ rb_econv_asciicompat_encoding(const char *ascii_incompat_name)
19191913
}
19201914

19211915
}
1922-
19231916
}
19241917

19251918
return data.ascii_compat_name; // can be NULL
@@ -4561,9 +4554,9 @@ void
45614554
Init_transcode(void)
45624555
{
45634556
transcoder_table = st_init_strcasetable();
4564-
fast_transcoder_path_table = rb_managed_id_table_new(8); // NOTE: size is arbitrarily chosen
4557+
fast_transcoder_path_table = rb_managed_st_table_create_strcasetable(8); // NOTE: size is arbitrarily chosen
45654558
rb_gc_register_address(&fast_transcoder_path_table);
4566-
fast_transcoder_entry_table = rb_managed_id_table_new(8);
4559+
fast_transcoder_entry_table = rb_managed_st_table_create_strcasetable(8);
45674560
rb_gc_register_address(&fast_transcoder_entry_table);
45684561

45694562
id_destination_encoding = rb_intern_const("destination_encoding");

0 commit comments

Comments
 (0)