aboutsummaryrefslogtreecommitdiffstats
path: root/variable.c
diff options
context:
space:
mode:
authorJean Boussier <byroot@ruby-lang.org>2023-02-28 10:04:53 +0100
committerJean Boussier <jean.boussier@gmail.com>2023-03-01 08:56:56 +0100
commit40e5ee64f08c5a264b95dc2d35d5d3cbcbf858a0 (patch)
treee993dca97555715074bdbb00fd49aae54b8fca10 /variable.c
parentee83274f36cdbf1ad12c611273de1042a0f24441 (diff)
downloadruby-40e5ee64f08c5a264b95dc2d35d5d3cbcbf858a0.tar.gz
Implement Write Barrier for `autoload_table_type`
It's just a decorated st_table, so we call `RB_OBJ_WRITTEN` after inserting to it. We also call `RB_OBJ_WRITTEN` on delete for completeness even though it's a noop.
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/variable.c b/variable.c
index 26a00db7c4..1a417da08e 100644
--- a/variable.c
+++ b/variable.c
@@ -2099,7 +2099,7 @@ autoload_table_compact(void *ptr)
static const rb_data_type_t autoload_table_type = {
"autoload_table",
{autoload_table_mark, autoload_table_free, autoload_table_memsize, autoload_table_compact,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
#define check_autoload_table(av) \
@@ -2126,8 +2126,8 @@ autoload_data(VALUE mod, ID id)
// Look up the instance variable table for `autoload`, then index into that table with the given constant name `id`.
- VALUE tbl_value = rb_ivar_lookup(mod, autoload, 0);
- if (!tbl_value || !(tbl = check_autoload_table(tbl_value)) || !st_lookup(tbl, (st_data_t)id, &val)) {
+ VALUE tbl_value = rb_ivar_lookup(mod, autoload, Qfalse);
+ if (!RTEST(tbl_value) || !(tbl = check_autoload_table(tbl_value)) || !st_lookup(tbl, (st_data_t)id, &val)) {
return 0;
}
@@ -2323,17 +2323,18 @@ autoload_feature_lookup_or_create(VALUE feature, struct autoload_data **autoload
return autoload_data_value;
}
-static struct st_table *
+static VALUE
autoload_table_lookup_or_create(VALUE module)
{
- VALUE autoload_table_value = rb_ivar_lookup(module, autoload, 0);
- if (autoload_table_value) {
- return check_autoload_table(autoload_table_value);
+ VALUE autoload_table_value = rb_ivar_lookup(module, autoload, Qfalse);
+ if (RTEST(autoload_table_value)) {
+ return autoload_table_value;
}
else {
- autoload_table_value = TypedData_Wrap_Struct(0, &autoload_table_type, 0);
+ autoload_table_value = TypedData_Wrap_Struct(0, &autoload_table_type, NULL);
rb_class_ivar_set(module, autoload, autoload_table_value);
- return (DATA_PTR(autoload_table_value) = st_init_numtable());
+ RTYPEDDATA_DATA(autoload_table_value) = st_init_numtable();
+ return autoload_table_value;
}
}
@@ -2350,7 +2351,8 @@ autoload_synchronized(VALUE _arguments)
// Reset any state associated with any previous constant:
const_set(arguments->module, arguments->name, Qundef);
- struct st_table *autoload_table = autoload_table_lookup_or_create(arguments->module);
+ VALUE autoload_table_value = autoload_table_lookup_or_create(arguments->module);
+ struct st_table *autoload_table = check_autoload_table(autoload_table_value);
// Ensure the string is uniqued since we use an identity lookup:
VALUE feature = rb_fstring(arguments->feature);
@@ -2368,6 +2370,7 @@ autoload_synchronized(VALUE _arguments)
autoload_const->autoload_data_value = autoload_data_value;
ccan_list_add_tail(&autoload_data->constants, &autoload_const->cnode);
st_insert(autoload_table, (st_data_t)arguments->name, (st_data_t)autoload_const_value);
+ RB_OBJ_WRITTEN(autoload_table_value, Qundef, autoload_const_value);
}
return Qtrue;
@@ -2407,11 +2410,12 @@ autoload_delete(VALUE module, ID name)
RUBY_ASSERT(RB_TYPE_P(module, T_CLASS) || RB_TYPE_P(module, T_MODULE));
- VALUE table_value = rb_ivar_lookup(module, autoload, 0);
- if (table_value) {
+ VALUE table_value = rb_ivar_lookup(module, autoload, Qfalse);
+ if (RTEST(table_value)) {
struct st_table *table = check_autoload_table(table_value);
st_delete(table, &key, &load);
+ RB_OBJ_WRITTEN(table_value, load, Qundef);
/* Qfalse can indicate already deleted */
if (load != Qfalse) {