Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Write Barrier for autoload_table_type #7402

Merged
merged 1 commit into from Mar 1, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 16 additions & 12 deletions variable.c
Expand Up @@ -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) \
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}
}

Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down