Skip to content

Commit b3689b6

Browse files
committed
Make rclass_ext->const_tbl a managed object.
The table itself is a `rb_id_marked_table` and the values are `IMEMO/constentry`. This open the door to do RCU updates of constant tables.
1 parent 4356313 commit b3689b6

10 files changed

Lines changed: 126 additions & 180 deletions

File tree

class.c

Lines changed: 50 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -135,46 +135,42 @@ duplicate_classext_id_table(struct rb_id_table *orig, bool init_missing)
135135
return tbl;
136136
}
137137

138-
static rb_const_entry_t *
139-
duplicate_classext_const_entry(rb_const_entry_t *src, VALUE klass)
138+
static VALUE
139+
duplicate_classext_const_entry(VALUE src_value)
140140
{
141+
rb_const_entry_t *src = (rb_const_entry_t *)src_value;
142+
141143
// See also: setup_const_entry (variable.c)
142-
rb_const_entry_t *dst = ZALLOC(rb_const_entry_t);
144+
VALUE dst_value = rb_const_entry_new();
145+
rb_const_entry_t *dst = (rb_const_entry_t *)dst_value;
143146

144-
dst->flag = src->flag;
145-
dst->line = src->line;
146-
RB_OBJ_WRITE(klass, &dst->value, src->value);
147-
RB_OBJ_WRITE(klass, &dst->file, src->file);
147+
MEMCPY(dst, src, rb_const_entry_t, 1);
148+
RB_OBJ_WRITTEN(dst_value, Qundef, src->value);
149+
RB_OBJ_WRITTEN(dst_value, Qundef, src->file);
148150

149-
return dst;
151+
return dst_value;
150152
}
151153

152154
static enum rb_id_table_iterator_result
153155
duplicate_classext_const_tbl_i(ID key, VALUE value, void *data)
154156
{
155-
struct duplicate_id_tbl_data *arg = (struct duplicate_id_tbl_data *)data;
156-
rb_const_entry_t *entry = duplicate_classext_const_entry((rb_const_entry_t *)value, arg->klass);
157+
VALUE dst = (VALUE)data;
157158

158-
rb_id_table_insert(arg->tbl, key, (VALUE)entry);
159+
VALUE entry = duplicate_classext_const_entry(value);
160+
rb_marked_id_table_insert(dst, key, entry);
159161

160162
return ID_TABLE_CONTINUE;
161163
}
162164

163-
static struct rb_id_table *
164-
duplicate_classext_const_tbl(struct rb_id_table *src, VALUE klass)
165+
static VALUE
166+
duplicate_classext_const_tbl(VALUE src)
165167
{
166-
struct rb_id_table *dst;
167-
168-
if (!src)
169-
return NULL;
170-
171-
dst = rb_id_table_create(rb_id_table_size(src));
168+
if (!src) {
169+
return 0;
170+
}
172171

173-
struct duplicate_id_tbl_data data = {
174-
.tbl = dst,
175-
.klass = klass,
176-
};
177-
rb_id_table_foreach(src, duplicate_classext_const_tbl_i, (void *)&data);
172+
VALUE dst = rb_marked_id_table_dup(src);
173+
rb_marked_id_table_foreach(src, duplicate_classext_const_tbl_i, (void *)dst);
178174

179175
return dst;
180176
}
@@ -312,7 +308,7 @@ rb_class_duplicate_classext(rb_classext_t *orig, VALUE klass, const rb_namespace
312308
RCLASSEXT_SHARED_CONST_TBL(ext) = true;
313309
}
314310
else {
315-
RCLASSEXT_CONST_TBL(ext) = duplicate_classext_const_tbl(RCLASSEXT_CONST_TBL(orig), klass);
311+
RB_OBJ_WRITE(klass, &RCLASSEXT_CONST_TBL(ext), duplicate_classext_const_tbl(RCLASSEXT_CONST_TBL(orig)));
316312
RCLASSEXT_SHARED_CONST_TBL(ext) = false;
317313
}
318314
/*
@@ -898,29 +894,22 @@ clone_method_i(ID key, VALUE value, void *data)
898894
return ID_TABLE_CONTINUE;
899895
}
900896

901-
struct clone_const_arg {
902-
VALUE klass;
903-
struct rb_id_table *tbl;
904-
};
905-
906-
static int
907-
clone_const(ID key, const rb_const_entry_t *ce, struct clone_const_arg *arg)
897+
static enum rb_id_table_iterator_result
898+
clone_const_i(ID key, VALUE value, void *data)
908899
{
909-
rb_const_entry_t *nce = ALLOC(rb_const_entry_t);
900+
VALUE new_table = (VALUE)data;
901+
const rb_const_entry_t *ce = (const rb_const_entry_t *)value;
902+
903+
VALUE nce_value = rb_const_entry_new();
904+
rb_const_entry_t *nce = (rb_const_entry_t *)nce_value;
910905
MEMCPY(nce, ce, rb_const_entry_t, 1);
911-
RB_OBJ_WRITTEN(arg->klass, Qundef, ce->value);
912-
RB_OBJ_WRITTEN(arg->klass, Qundef, ce->file);
906+
RB_OBJ_WRITTEN(nce_value, Qundef, ce->value);
907+
RB_OBJ_WRITTEN(nce_value, Qundef, ce->file);
913908

914-
rb_id_table_insert(arg->tbl, key, (VALUE)nce);
909+
rb_marked_id_table_insert(new_table, key, (VALUE)nce);
915910
return ID_TABLE_CONTINUE;
916911
}
917912

918-
static enum rb_id_table_iterator_result
919-
clone_const_i(ID key, VALUE value, void *data)
920-
{
921-
return clone_const(key, (const rb_const_entry_t *)value, data);
922-
}
923-
924913
static void
925914
class_init_copy_check(VALUE clone, VALUE orig)
926915
{
@@ -964,7 +953,6 @@ static void
964953
copy_tables(VALUE clone, VALUE orig)
965954
{
966955
if (RCLASS_CONST_TBL(clone)) {
967-
rb_free_const_table(RCLASS_CONST_TBL(clone));
968956
RCLASS_WRITE_CONST_TBL(clone, 0, false);
969957
}
970958
if (RCLASS_CVC_TBL(orig)) {
@@ -982,14 +970,12 @@ copy_tables(VALUE clone, VALUE orig)
982970
if (!RB_TYPE_P(clone, T_ICLASS)) {
983971
rb_fields_tbl_copy(clone, orig);
984972
}
985-
if (RCLASS_CONST_TBL(orig)) {
986-
struct clone_const_arg arg;
987-
struct rb_id_table *const_tbl;
988-
struct rb_id_table *orig_tbl = RCLASS_CONST_TBL(orig);
989-
arg.tbl = const_tbl = rb_id_table_create(rb_id_table_size(orig_tbl));
990-
arg.klass = clone;
991-
rb_id_table_foreach(orig_tbl, clone_const_i, &arg);
992-
RCLASS_WRITE_CONST_TBL(clone, const_tbl, false);
973+
974+
VALUE const_table = RCLASS_CONST_TBL(orig);
975+
if (const_table) {
976+
VALUE new_const_tbl = rb_marked_id_table_new(rb_marked_id_table_size(const_table));
977+
rb_marked_id_table_foreach(const_table, clone_const_i, (void *)new_const_tbl);
978+
RCLASS_WRITE_CONST_TBL(clone, new_const_tbl, false);
993979
}
994980
}
995981

@@ -1177,14 +1163,15 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
11771163

11781164
rb_class_set_super(clone, RCLASS_SUPER(klass));
11791165
rb_fields_tbl_copy(clone, klass);
1180-
if (RCLASS_CONST_TBL(klass)) {
1181-
struct clone_const_arg arg;
1182-
struct rb_id_table *table;
1183-
arg.tbl = table = rb_id_table_create(0);
1184-
arg.klass = clone;
1185-
rb_id_table_foreach(RCLASS_CONST_TBL(klass), clone_const_i, &arg);
1186-
RCLASS_SET_CONST_TBL(clone, table, false);
1166+
1167+
1168+
VALUE const_table = RCLASS_CONST_TBL(klass);
1169+
if (const_table) {
1170+
VALUE new_const_tbl = rb_marked_id_table_new(rb_marked_id_table_size(const_table));
1171+
rb_marked_id_table_foreach(const_table, clone_const_i, (void *)new_const_tbl);
1172+
RCLASS_WRITE_CONST_TBL(clone, new_const_tbl, false);
11871173
}
1174+
11881175
if (!UNDEF_P(attach)) {
11891176
rb_singleton_class_attached(clone, attach);
11901177
}
@@ -1669,7 +1656,7 @@ rb_include_class_new(VALUE module, VALUE super)
16691656
RCLASS_SET_CONST_TBL(klass, RCLASS_WRITABLE_CONST_TBL(module), true);
16701657
}
16711658
else {
1672-
RCLASS_WRITE_CONST_TBL(module, rb_id_table_create(0), false);
1659+
RCLASS_WRITE_CONST_TBL(module, Qfalse, false);
16731660
RCLASS_SET_CONST_TBL(klass, RCLASS_WRITABLE_CONST_TBL(module), true);
16741661
}
16751662

@@ -1863,9 +1850,10 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
18631850
RUBY_ASSERT(BUILTIN_TYPE(c) == T_MODULE);
18641851
}
18651852

1866-
tbl = RCLASS_CONST_TBL(module);
1867-
if (tbl && rb_id_table_size(tbl))
1868-
rb_id_table_foreach(tbl, clear_constant_cache_i, NULL);
1853+
VALUE const_table = RCLASS_CONST_TBL(module);
1854+
if (const_table) {
1855+
rb_marked_id_table_foreach(const_table, clear_constant_cache_i, NULL);
1856+
}
18691857
skip:
18701858
module = RCLASS_SUPER(module);
18711859
}

constant.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,19 @@ typedef enum {
3030
#define RB_CONST_DEPRECATED_P(ce) \
3131
((ce)->flag & CONST_DEPRECATED)
3232

33+
// imemo_constentry
3334
typedef struct rb_const_entry_struct {
34-
rb_const_flag_t flag;
35-
int line;
35+
VALUE _imemo_flags;
36+
3637
VALUE value; /* should be mark */
3738
VALUE file; /* should be mark */
39+
int line;
40+
rb_const_flag_t flag;
3841
} rb_const_entry_t;
3942

4043
VALUE rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj);
4144
VALUE rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj);
4245
VALUE rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj);
43-
void rb_free_const_table(struct rb_id_table *tbl);
4446
VALUE rb_const_source_location(VALUE, ID);
4547

4648
int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag);

debug_counter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ RB_DEBUG_COUNTER(obj_imemo_parser_strterm)
315315
RB_DEBUG_COUNTER(obj_imemo_callinfo)
316316
RB_DEBUG_COUNTER(obj_imemo_callcache)
317317
RB_DEBUG_COUNTER(obj_imemo_constcache)
318+
RB_DEBUG_COUNTER(obj_imemo_constentry)
318319
RB_DEBUG_COUNTER(obj_imemo_fields)
319320

320321
RB_DEBUG_COUNTER(opt_new_hit)

gc.c

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,9 +1212,6 @@ classext_free(rb_classext_t *ext, bool is_prime, VALUE namespace, void *arg)
12121212

12131213
rb_id_table_free(RCLASSEXT_M_TBL(ext));
12141214
rb_cc_tbl_free(RCLASSEXT_CC_TBL(ext), args->klass);
1215-
if (!RCLASSEXT_SHARED_CONST_TBL(ext) && (tbl = RCLASSEXT_CONST_TBL(ext)) != NULL) {
1216-
rb_free_const_table(tbl);
1217-
}
12181215
if ((tbl = RCLASSEXT_CVC_TBL(ext)) != NULL) {
12191216
rb_id_table_foreach_values(tbl, cvar_table_free_i, NULL);
12201217
rb_id_table_free(tbl);
@@ -2268,9 +2265,6 @@ classext_memsize(rb_classext_t *ext, bool prime, VALUE namespace, void *arg)
22682265
if (RCLASSEXT_CVC_TBL(ext)) {
22692266
s += rb_id_table_memsize(RCLASSEXT_CVC_TBL(ext));
22702267
}
2271-
if (RCLASSEXT_CONST_TBL(ext)) {
2272-
s += rb_id_table_memsize(RCLASSEXT_CONST_TBL(ext));
2273-
}
22742268
if (RCLASSEXT_CC_TBL(ext)) {
22752269
s += cc_table_memsize(RCLASSEXT_CC_TBL(ext));
22762270
}
@@ -2786,23 +2780,6 @@ mark_m_tbl(void *objspace, struct rb_id_table *tbl)
27862780
}
27872781
}
27882782

2789-
static enum rb_id_table_iterator_result
2790-
mark_const_entry_i(VALUE value, void *objspace)
2791-
{
2792-
const rb_const_entry_t *ce = (const rb_const_entry_t *)value;
2793-
2794-
gc_mark_internal(ce->value);
2795-
gc_mark_internal(ce->file);
2796-
return ID_TABLE_CONTINUE;
2797-
}
2798-
2799-
static void
2800-
mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
2801-
{
2802-
if (!tbl) return;
2803-
rb_id_table_foreach_values(tbl, mark_const_entry_i, objspace);
2804-
}
2805-
28062783
struct mark_cc_entry_args {
28072784
rb_objspace_t *objspace;
28082785
VALUE klass;
@@ -3088,9 +3065,7 @@ gc_mark_classext_module(rb_classext_t *ext, bool prime, VALUE namespace, void *a
30883065
}
30893066
mark_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
30903067
gc_mark_internal(RCLASSEXT_FIELDS_OBJ(ext));
3091-
if (!RCLASSEXT_SHARED_CONST_TBL(ext) && RCLASSEXT_CONST_TBL(ext)) {
3092-
mark_const_tbl(objspace, RCLASSEXT_CONST_TBL(ext));
3093-
}
3068+
gc_mark_internal(RCLASSEXT_CONST_TBL(ext));
30943069
mark_m_tbl(objspace, RCLASSEXT_CALLABLE_M_TBL(ext));
30953070
mark_cc_tbl(objspace, RCLASSEXT_CC_TBL(ext), obj);
30963071
mark_cvc_tbl(objspace, RCLASSEXT_CVC_TBL(ext));
@@ -3729,29 +3704,6 @@ update_cvc_tbl(void *objspace, struct rb_id_table *tbl)
37293704
rb_id_table_foreach_values(tbl, update_cvc_tbl_i, objspace);
37303705
}
37313706

3732-
static enum rb_id_table_iterator_result
3733-
update_const_tbl_i(VALUE value, void *objspace)
3734-
{
3735-
rb_const_entry_t *ce = (rb_const_entry_t *)value;
3736-
3737-
if (rb_gc_impl_object_moved_p(objspace, ce->value)) {
3738-
ce->value = gc_location_internal(objspace, ce->value);
3739-
}
3740-
3741-
if (rb_gc_impl_object_moved_p(objspace, ce->file)) {
3742-
ce->file = gc_location_internal(objspace, ce->file);
3743-
}
3744-
3745-
return ID_TABLE_CONTINUE;
3746-
}
3747-
3748-
static void
3749-
update_const_tbl(void *objspace, struct rb_id_table *tbl)
3750-
{
3751-
if (!tbl) return;
3752-
rb_id_table_foreach_values(tbl, update_const_tbl_i, objspace);
3753-
}
3754-
37553707
static void
37563708
update_subclasses(void *objspace, rb_classext_t *ext)
37573709
{
@@ -3801,9 +3753,7 @@ update_classext(rb_classext_t *ext, bool is_prime, VALUE namespace, void *arg)
38013753
update_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
38023754

38033755
UPDATE_IF_MOVED(objspace, ext->fields_obj);
3804-
if (!RCLASSEXT_SHARED_CONST_TBL(ext)) {
3805-
update_const_tbl(objspace, RCLASSEXT_CONST_TBL(ext));
3806-
}
3756+
UPDATE_IF_MOVED(objspace, RCLASSEXT_CONST_TBL(ext));
38073757
update_cc_tbl(objspace, RCLASSEXT_CC_TBL(ext));
38083758
update_cvc_tbl(objspace, RCLASSEXT_CVC_TBL(ext));
38093759
update_superclasses(objspace, ext);
@@ -3822,6 +3772,7 @@ update_iclass_classext(rb_classext_t *ext, bool is_prime, VALUE namespace, void
38223772
UPDATE_IF_MOVED(objspace, RCLASSEXT_SUPER(ext));
38233773
}
38243774
update_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
3775+
UPDATE_IF_MOVED(objspace, RCLASSEXT_CONST_TBL(ext));
38253776
update_m_tbl(objspace, RCLASSEXT_CALLABLE_M_TBL(ext));
38263777
update_cc_tbl(objspace, RCLASSEXT_CC_TBL(ext));
38273778
update_subclasses(objspace, ext);

imemo.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ rb_imemo_name(enum imemo_type type)
2020
IMEMO_NAME(callcache);
2121
IMEMO_NAME(callinfo);
2222
IMEMO_NAME(constcache);
23+
IMEMO_NAME(constentry);
2324
IMEMO_NAME(cref);
2425
IMEMO_NAME(env);
2526
IMEMO_NAME(ifunc);
@@ -231,6 +232,8 @@ rb_imemo_memsize(VALUE obj)
231232
break;
232233
case imemo_constcache:
233234
break;
235+
case imemo_constentry:
236+
break;
234237
case imemo_cref:
235238
break;
236239
case imemo_env:
@@ -439,6 +442,14 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
439442

440443
break;
441444
}
445+
case imemo_constentry: {
446+
rb_const_entry_t *ce = (rb_const_entry_t *)obj;
447+
448+
rb_gc_mark_and_move(&ce->value);
449+
rb_gc_mark_and_move(&ce->file);
450+
451+
break;
452+
}
442453
case imemo_cref: {
443454
rb_cref_t *cref = (rb_cref_t *)obj;
444455

@@ -561,21 +572,6 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
561572
* free
562573
* ========================================================================= */
563574

564-
static enum rb_id_table_iterator_result
565-
free_const_entry_i(VALUE value, void *data)
566-
{
567-
rb_const_entry_t *ce = (rb_const_entry_t *)value;
568-
xfree(ce);
569-
return ID_TABLE_CONTINUE;
570-
}
571-
572-
void
573-
rb_free_const_table(struct rb_id_table *tbl)
574-
{
575-
rb_id_table_foreach_values(tbl, free_const_entry_i, 0);
576-
rb_id_table_free(tbl);
577-
}
578-
579575
// alive: if false, target pointers can be freed already.
580576
static void
581577
vm_ccs_free(struct rb_class_cc_entries *ccs, int alive, VALUE klass)
@@ -682,6 +678,10 @@ rb_imemo_free(VALUE obj)
682678
case imemo_constcache:
683679
RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
684680

681+
break;
682+
case imemo_constentry:
683+
RB_DEBUG_COUNTER_INC(obj_imemo_constentry);
684+
685685
break;
686686
case imemo_cref:
687687
RB_DEBUG_COUNTER_INC(obj_imemo_cref);

0 commit comments

Comments
 (0)