mirror of
https://github.com/ruby/ruby.git
synced 2026-01-27 04:24:23 +00:00
Box: Free rb_classext_t struct for a box when the box is GCed
This commit is contained in:
parent
84bc1f038a
commit
9eafeaed67
Notes:
git
2025-12-02 14:50:23 +00:00
32
box.c
32
box.c
@ -149,6 +149,7 @@ box_entry_initialize(rb_box_t *box)
|
||||
box->loading_table = st_init_strtable();
|
||||
box->ruby_dln_libmap = rb_hash_new_with_size(0);
|
||||
box->gvar_tbl = rb_hash_new_with_size(0);
|
||||
box->classext_cow_classes = st_init_numtable();
|
||||
|
||||
box->is_user = true;
|
||||
box->is_optional = true;
|
||||
@ -199,6 +200,9 @@ rb_box_entry_mark(void *ptr)
|
||||
}
|
||||
rb_gc_mark(box->ruby_dln_libmap);
|
||||
rb_gc_mark(box->gvar_tbl);
|
||||
if (box->classext_cow_classes) {
|
||||
rb_mark_tbl(box->classext_cow_classes);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@ -233,9 +237,36 @@ box_root_free(void *ptr)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
free_classext_for_box(st_data_t _key, st_data_t obj_value, st_data_t box_arg)
|
||||
{
|
||||
rb_classext_t *ext;
|
||||
VALUE obj = (VALUE)obj_value;
|
||||
const rb_box_t *box = (const rb_box_t *)box_arg;
|
||||
|
||||
if (RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE)) {
|
||||
ext = rb_class_unlink_classext(obj, box);
|
||||
rb_class_classext_free(obj, ext, false);
|
||||
}
|
||||
else if (RB_TYPE_P(obj, T_ICLASS)) {
|
||||
ext = rb_class_unlink_classext(obj, box);
|
||||
rb_iclass_classext_free(obj, ext, false);
|
||||
}
|
||||
else {
|
||||
rb_bug("Invalid type of object in classext_cow_classes: %s", rb_type_str(BUILTIN_TYPE(obj)));
|
||||
}
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
box_entry_free(void *ptr)
|
||||
{
|
||||
const rb_box_t *box = (const rb_box_t *)ptr;
|
||||
|
||||
if (box->classext_cow_classes) {
|
||||
st_foreach(box->classext_cow_classes, free_classext_for_box, (st_data_t)box);
|
||||
}
|
||||
|
||||
box_root_free(ptr);
|
||||
xfree(ptr);
|
||||
}
|
||||
@ -750,6 +781,7 @@ initialize_root_box(void)
|
||||
|
||||
root->ruby_dln_libmap = rb_hash_new_with_size(0);
|
||||
root->gvar_tbl = rb_hash_new_with_size(0);
|
||||
root->classext_cow_classes = NULL; // classext CoW never happen on the root box
|
||||
|
||||
vm->root_box = root;
|
||||
|
||||
|
||||
18
class.c
18
class.c
@ -86,6 +86,17 @@ cvar_table_free_i(VALUE value, void *ctx)
|
||||
return ID_TABLE_CONTINUE;
|
||||
}
|
||||
|
||||
rb_classext_t *
|
||||
rb_class_unlink_classext(VALUE klass, const rb_box_t *box)
|
||||
{
|
||||
st_data_t ext;
|
||||
st_data_t key = (st_data_t)box->box_object;
|
||||
VALUE obj_id = rb_obj_id(klass);
|
||||
st_delete(box->classext_cow_classes, &obj_id, 0);
|
||||
st_delete(RCLASS_CLASSEXT_TBL(klass), &key, &ext);
|
||||
return (rb_classext_t *)ext;
|
||||
}
|
||||
|
||||
void
|
||||
rb_class_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime)
|
||||
{
|
||||
@ -156,7 +167,7 @@ struct rb_class_set_box_classext_args {
|
||||
};
|
||||
|
||||
static int
|
||||
rb_class_set_box_classext_update(st_data_t *key_ptr, st_data_t *val_ptr, st_data_t a, int existing)
|
||||
set_box_classext_update(st_data_t *key_ptr, st_data_t *val_ptr, st_data_t a, int existing)
|
||||
{
|
||||
struct rb_class_set_box_classext_args *args = (struct rb_class_set_box_classext_args *)a;
|
||||
|
||||
@ -182,7 +193,10 @@ rb_class_set_box_classext(VALUE obj, const rb_box_t *box, rb_classext_t *ext)
|
||||
.ext = ext,
|
||||
};
|
||||
|
||||
st_update(RCLASS_CLASSEXT_TBL(obj), (st_data_t)box->box_object, rb_class_set_box_classext_update, (st_data_t)&args);
|
||||
VM_ASSERT(BOX_USER_P(box));
|
||||
|
||||
st_update(RCLASS_CLASSEXT_TBL(obj), (st_data_t)box->box_object, set_box_classext_update, (st_data_t)&args);
|
||||
st_insert(box->classext_cow_classes, (st_data_t)rb_obj_id(obj), obj);
|
||||
|
||||
// FIXME: This is done here because this is the first time the objects in
|
||||
// the classext are exposed via this class. It's likely that if GC
|
||||
|
||||
@ -34,6 +34,7 @@ struct rb_box_struct {
|
||||
VALUE ruby_dln_libmap;
|
||||
|
||||
VALUE gvar_tbl;
|
||||
struct st_table *classext_cow_classes;
|
||||
|
||||
bool is_user;
|
||||
bool is_optional;
|
||||
|
||||
@ -513,6 +513,7 @@ void rb_undef_methods_from(VALUE klass, VALUE super);
|
||||
VALUE rb_class_inherited(VALUE, VALUE);
|
||||
VALUE rb_keyword_error_new(const char *, VALUE);
|
||||
|
||||
rb_classext_t *rb_class_unlink_classext(VALUE klass, const rb_box_t *box);
|
||||
void rb_class_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime);
|
||||
void rb_iclass_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user