summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorSatoshi Tagomori <[email protected]>2025-04-30 13:48:02 +0900
committerSatoshi Tagomori <[email protected]>2025-05-11 23:32:50 +0900
commit382645d440d5da66a0c04557f3ff2ca226de3a27 (patch)
treeb7453449930197237e739d0985561b664f51b0f3 /gc.c
parent49742414f6444960838bb968bab43db27f5872c1 (diff)
namespace on read
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c527
1 files changed, 360 insertions, 167 deletions
diff --git a/gc.c b/gc.c
index d728cd0fe3..630f853c39 100644
--- a/gc.c
+++ b/gc.c
@@ -1210,9 +1210,68 @@ rb_data_free(void *objspace, VALUE obj)
return true;
}
+struct classext_foreach_args {
+ VALUE klass;
+ bool obj_too_complex;
+ rb_objspace_t *objspace; // used for update_*
+};
+
+static void
+classext_free(rb_classext_t *ext, bool is_prime, VALUE namespace, void *arg)
+{
+ struct rb_id_table *tbl;
+ struct classext_foreach_args *args = (struct classext_foreach_args *)arg;
+
+ rb_id_table_free(RCLASSEXT_M_TBL(ext));
+ rb_cc_tbl_free(RCLASSEXT_CC_TBL(ext), args->klass);
+ if (args->obj_too_complex) {
+ st_free_table((st_table *)RCLASSEXT_FIELDS(ext));
+ }
+ else {
+ xfree(RCLASSEXT_FIELDS(ext));
+ }
+ if (!RCLASSEXT_SHARED_CONST_TBL(ext) && (tbl = RCLASSEXT_CONST_TBL(ext)) != NULL) {
+ rb_free_const_table(tbl);
+ }
+ if ((tbl = RCLASSEXT_CVC_TBL(ext)) != NULL) {
+ rb_id_table_foreach_values(tbl, cvar_table_free_i, NULL);
+ rb_id_table_free(tbl);
+ }
+ rb_class_classext_free_subclasses(ext, args->klass);
+ if (RCLASSEXT_SUPERCLASSES_OWNER(ext)) {
+ xfree(RCLASSEXT_SUPERCLASSES(ext));
+ }
+ if (!is_prime) { // the prime classext will be freed with RClass
+ xfree(ext);
+ }
+}
+
+static void
+classext_iclass_free(rb_classext_t *ext, bool is_prime, VALUE namespace, void *arg)
+{
+ struct classext_foreach_args *args = (struct classext_foreach_args *)arg;
+
+ if (RCLASSEXT_ICLASS_IS_ORIGIN(ext) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext)) {
+ /* Method table is not shared for origin iclasses of classes */
+ rb_id_table_free(RCLASSEXT_M_TBL(ext));
+ }
+ if (RCLASSEXT_CALLABLE_M_TBL(ext) != NULL) {
+ rb_id_table_free(RCLASSEXT_CALLABLE_M_TBL(ext));
+ }
+ rb_cc_tbl_free(RCLASSEXT_CC_TBL(ext), args->klass);
+
+ rb_class_classext_free_subclasses(ext, args->klass);
+
+ if (!is_prime) { // the prime classext will be freed with RClass
+ xfree(ext);
+ }
+}
+
bool
rb_gc_obj_free(void *objspace, VALUE obj)
{
+ struct classext_foreach_args args;
+
RB_DEBUG_COUNTER_INC(obj_free);
switch (BUILTIN_TYPE(obj)) {
@@ -1242,29 +1301,13 @@ rb_gc_obj_free(void *objspace, VALUE obj)
break;
case T_MODULE:
case T_CLASS:
- rb_id_table_free(RCLASS_M_TBL(obj));
- rb_cc_table_free(obj);
- if (rb_shape_obj_too_complex_p(obj)) {
- st_free_table((st_table *)RCLASS_FIELDS(obj));
- }
- else {
- xfree(RCLASS_FIELDS(obj));
- }
+ args.klass = obj;
+ args.obj_too_complex = rb_shape_obj_too_complex_p(obj) ? true : false;
- if (RCLASS_CONST_TBL(obj)) {
- rb_free_const_table(RCLASS_CONST_TBL(obj));
- }
- if (RCLASS_CVC_TBL(obj)) {
- rb_id_table_foreach_values(RCLASS_CVC_TBL(obj), cvar_table_free_i, NULL);
- rb_id_table_free(RCLASS_CVC_TBL(obj));
+ rb_class_classext_foreach(obj, classext_free, (void *)&args);
+ if (RCLASS(obj)->ns_classext_tbl) {
+ st_free_table(RCLASS(obj)->ns_classext_tbl);
}
- rb_class_remove_subclass_head(obj);
- rb_class_remove_from_module_subclasses(obj);
- rb_class_remove_from_super_subclasses(obj);
- if (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
- xfree(RCLASS_SUPERCLASSES(obj));
- }
-
(void)RB_DEBUG_COUNTER_INC_IF(obj_module_ptr, BUILTIN_TYPE(obj) == T_MODULE);
(void)RB_DEBUG_COUNTER_INC_IF(obj_class_ptr, BUILTIN_TYPE(obj) == T_CLASS);
break;
@@ -1363,18 +1406,12 @@ rb_gc_obj_free(void *objspace, VALUE obj)
case T_MOVED:
break;
case T_ICLASS:
- /* Basically , T_ICLASS shares table with the module */
- if (RICLASS_OWNS_M_TBL_P(obj)) {
- /* Method table is not shared for origin iclasses of classes */
- rb_id_table_free(RCLASS_M_TBL(obj));
- }
- if (RCLASS_CALLABLE_M_TBL(obj) != NULL) {
- rb_id_table_free(RCLASS_CALLABLE_M_TBL(obj));
+ args.klass = obj;
+
+ rb_class_classext_foreach(obj, classext_iclass_free, (void *)&args);
+ if (RCLASS(obj)->ns_classext_tbl) {
+ st_free_table(RCLASS(obj)->ns_classext_tbl);
}
- rb_class_remove_subclass_head(obj);
- rb_cc_table_free(obj);
- rb_class_remove_from_module_subclasses(obj);
- rb_class_remove_from_super_subclasses(obj);
RB_DEBUG_COUNTER_INC(obj_iclass_ptr);
break;
@@ -2124,6 +2161,60 @@ cc_table_memsize(struct rb_id_table *cc_table)
return total;
}
+static void
+classext_memsize(rb_classext_t *ext, bool prime, VALUE namespace, void *arg)
+{
+ size_t *size = (size_t *)arg;
+ size_t s = 0;
+
+ if (RCLASSEXT_M_TBL(ext)) {
+ s += rb_id_table_memsize(RCLASSEXT_M_TBL(ext));
+ }
+ if (RCLASSEXT_CVC_TBL(ext)) {
+ s += rb_id_table_memsize(RCLASSEXT_CVC_TBL(ext));
+ }
+ if (RCLASSEXT_CONST_TBL(ext)) {
+ s += rb_id_table_memsize(RCLASSEXT_CONST_TBL(ext));
+ }
+ if (RCLASSEXT_CC_TBL(ext)) {
+ s += cc_table_memsize(RCLASSEXT_CC_TBL(ext));
+ }
+ if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) {
+ s += (RCLASSEXT_SUPERCLASS_DEPTH(ext) + 1) * sizeof(VALUE);
+ }
+ if (!prime) {
+ s += sizeof(rb_classext_t);
+ }
+ *size += s;
+}
+
+static void
+classext_fields_hash_memsize(rb_classext_t *ext, bool prime, VALUE namespace, void *arg)
+{
+ size_t *size = (size_t *)arg;
+ size_t count;
+ RB_VM_LOCK_ENTER();
+ {
+ count = rb_st_table_size((st_table *)RCLASSEXT_FIELDS(ext));
+ }
+ RB_VM_LOCK_LEAVE();
+ // class IV sizes are allocated as powers of two
+ *size += SIZEOF_VALUE << bit_length(count);
+}
+
+static void
+classext_superclasses_memsize(rb_classext_t *ext, bool prime, VALUE namespace, void *arg)
+{
+ size_t *size = (size_t *)arg;
+ size_t array_size;
+ if (RCLASSEXT_SUPERCLASSES_OWNER(ext)) {
+ array_size = RCLASSEXT_SUPERCLASS_DEPTH(ext);
+ if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext))
+ array_size += 1;
+ *size += array_size * sizeof(VALUE);
+ }
+}
+
size_t
rb_obj_memsize_of(VALUE obj)
{
@@ -2148,23 +2239,16 @@ rb_obj_memsize_of(VALUE obj)
break;
case T_MODULE:
case T_CLASS:
- if (RCLASS_M_TBL(obj)) {
- size += rb_id_table_memsize(RCLASS_M_TBL(obj));
- }
- // class IV sizes are allocated as powers of two
- size += SIZEOF_VALUE << bit_length(RCLASS_FIELDS_COUNT(obj));
- if (RCLASS_CVC_TBL(obj)) {
- size += rb_id_table_memsize(RCLASS_CVC_TBL(obj));
- }
- if (RCLASS_EXT(obj)->const_tbl) {
- size += rb_id_table_memsize(RCLASS_EXT(obj)->const_tbl);
- }
- if (RCLASS_CC_TBL(obj)) {
- size += cc_table_memsize(RCLASS_CC_TBL(obj));
- }
- if (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
- size += (RCLASS_SUPERCLASS_DEPTH(obj) + 1) * sizeof(VALUE);
+ rb_class_classext_foreach(obj, classext_memsize, (void *)&size);
+
+ if (rb_shape_obj_too_complex_p(obj)) {
+ rb_class_classext_foreach(obj, classext_fields_hash_memsize, (void *)&size);
+ } else {
+ // class IV sizes are allocated as powers of two
+ size += SIZEOF_VALUE << bit_length(RCLASS_FIELDS_COUNT(obj));
}
+
+ rb_class_classext_foreach(obj, classext_superclasses_memsize, (void *)&size);
break;
case T_ICLASS:
if (RICLASS_OWNS_M_TBL_P(obj)) {
@@ -2172,8 +2256,8 @@ rb_obj_memsize_of(VALUE obj)
size += rb_id_table_memsize(RCLASS_M_TBL(obj));
}
}
- if (RCLASS_CC_TBL(obj)) {
- size += cc_table_memsize(RCLASS_CC_TBL(obj));
+ if (RCLASS_WRITABLE_CC_TBL(obj)) {
+ size += cc_table_memsize(RCLASS_WRITABLE_CC_TBL(obj));
}
break;
case T_STRING:
@@ -2634,6 +2718,86 @@ mark_m_tbl(void *objspace, struct rb_id_table *tbl)
}
}
+static enum rb_id_table_iterator_result
+mark_const_entry_i(VALUE value, void *objspace)
+{
+ const rb_const_entry_t *ce = (const rb_const_entry_t *)value;
+
+ gc_mark_internal(ce->value);
+ gc_mark_internal(ce->file);
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
+{
+ if (!tbl) return;
+ rb_id_table_foreach_values(tbl, mark_const_entry_i, objspace);
+}
+
+struct mark_cc_entry_args {
+ rb_objspace_t *objspace;
+ VALUE klass;
+};
+
+static enum rb_id_table_iterator_result
+mark_cc_entry_i(ID id, VALUE ccs_ptr, void *data)
+{
+ struct mark_cc_entry_args *args = (struct mark_cc_entry_args *)data;
+ struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
+
+ VM_ASSERT(vm_ccs_p(ccs));
+ VM_ASSERT(id == ccs->cme->called_id);
+
+ if (METHOD_ENTRY_INVALIDATED(ccs->cme)) {
+ rb_vm_ccs_free(ccs);
+ return ID_TABLE_DELETE;
+ }
+ else {
+ gc_mark_internal((VALUE)ccs->cme);
+
+ for (int i=0; i<ccs->len; i++) {
+ VM_ASSERT(args->klass == ccs->entries[i].cc->klass);
+ VM_ASSERT(vm_cc_check_cme(ccs->entries[i].cc, ccs->cme));
+
+ gc_mark_internal((VALUE)ccs->entries[i].cc);
+ }
+ return ID_TABLE_CONTINUE;
+ }
+}
+
+static void
+mark_cc_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl, VALUE klass)
+{
+ struct mark_cc_entry_args args;
+
+ if (!tbl) return;
+
+ args.objspace = objspace;
+ args.klass = klass;
+ rb_id_table_foreach(tbl, mark_cc_entry_i, (void *)&args);
+}
+
+static enum rb_id_table_iterator_result
+mark_cvc_tbl_i(VALUE cvc_entry, void *objspace)
+{
+ struct rb_cvar_class_tbl_entry *entry;
+
+ entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
+
+ RUBY_ASSERT(entry->cref == 0 || (BUILTIN_TYPE((VALUE)entry->cref) == T_IMEMO && IMEMO_TYPE_P(entry->cref, imemo_cref)));
+ gc_mark_internal((VALUE)entry->cref);
+
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+mark_cvc_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
+{
+ if (!tbl) return;
+ rb_id_table_foreach_values(tbl, mark_cvc_tbl_i, objspace);
+}
+
#if STACK_GROW_DIRECTION < 0
#define GET_STACK_BOUNDS(start, end, appendix) ((start) = STACK_END, (end) = STACK_START)
#elif STACK_GROW_DIRECTION > 0
@@ -2796,45 +2960,12 @@ rb_mark_tbl_no_pin(st_table *tbl)
gc_mark_tbl_no_pin(tbl);
}
-static enum rb_id_table_iterator_result
-mark_cvc_tbl_i(VALUE cvc_entry, void *objspace)
-{
- struct rb_cvar_class_tbl_entry *entry;
-
- entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
-
- RUBY_ASSERT(entry->cref == 0 || (BUILTIN_TYPE((VALUE)entry->cref) == T_IMEMO && IMEMO_TYPE_P(entry->cref, imemo_cref)));
- gc_mark_internal((VALUE)entry->cref);
-
- return ID_TABLE_CONTINUE;
-}
-
-static void
-mark_cvc_tbl(void *objspace, VALUE klass)
-{
- struct rb_id_table *tbl = RCLASS_CVC_TBL(klass);
- if (tbl) {
- rb_id_table_foreach_values(tbl, mark_cvc_tbl_i, objspace);
- }
-}
-
static bool
gc_declarative_marking_p(const rb_data_type_t *type)
{
return (type->flags & RUBY_TYPED_DECL_MARKING) != 0;
}
-static enum rb_id_table_iterator_result
-mark_const_table_i(VALUE value, void *objspace)
-{
- const rb_const_entry_t *ce = (const rb_const_entry_t *)value;
-
- gc_mark_internal(ce->value);
- gc_mark_internal(ce->file);
-
- return ID_TABLE_CONTINUE;
-}
-
void
rb_gc_mark_roots(void *objspace, const char **categoryp)
{
@@ -2875,11 +3006,62 @@ rb_gc_mark_roots(void *objspace, const char **categoryp)
#undef MARK_CHECKPOINT
}
+struct gc_mark_classext_foreach_arg {
+ rb_objspace_t *objspace;
+ VALUE obj;
+};
+
+static void
+gc_mark_classext_module(rb_classext_t *ext, bool prime, VALUE namespace, void *arg)
+{
+ struct gc_mark_classext_foreach_arg *foreach_arg = (struct gc_mark_classext_foreach_arg *)arg;
+ rb_objspace_t *objspace = foreach_arg->objspace;
+ VALUE obj = foreach_arg->obj;
+
+ if (RCLASSEXT_SUPER(ext)) {
+ gc_mark_internal(RCLASSEXT_SUPER(ext));
+ }
+ mark_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
+ if (rb_shape_obj_too_complex_p(obj)) {
+ gc_mark_tbl_no_pin((st_table *)RCLASSEXT_FIELDS(ext));
+ // for the case ELSE is written in rb_gc_mark_children() because it's per RClass, not classext
+ }
+ if (!RCLASSEXT_SHARED_CONST_TBL(ext) && RCLASSEXT_CONST_TBL(ext)) {
+ mark_const_tbl(objspace, RCLASSEXT_CONST_TBL(ext));
+ }
+ mark_m_tbl(objspace, RCLASSEXT_CALLABLE_M_TBL(ext));
+ mark_cc_tbl(objspace, RCLASSEXT_CC_TBL(ext), obj);
+ mark_cvc_tbl(objspace, RCLASSEXT_CVC_TBL(ext));
+ gc_mark_internal(RCLASSEXT_CLASSPATH(ext));
+}
+
+static void
+gc_mark_classext_iclass(rb_classext_t *ext, bool prime, VALUE namespace, void *arg)
+{
+ struct gc_mark_classext_foreach_arg *foreach_arg = (struct gc_mark_classext_foreach_arg *)arg;
+ rb_objspace_t *objspace = foreach_arg->objspace;
+ VALUE iclass = foreach_arg->obj;
+
+ if (RCLASSEXT_SUPER(ext)) {
+ gc_mark_internal(RCLASSEXT_SUPER(ext));
+ }
+ if (RCLASSEXT_ICLASS_IS_ORIGIN(ext) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext)) {
+ mark_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
+ }
+ if (RCLASSEXT_INCLUDER(ext)) {
+ gc_mark_internal(RCLASSEXT_INCLUDER(ext));
+ }
+ mark_m_tbl(objspace, RCLASSEXT_CALLABLE_M_TBL(ext));
+ mark_cc_tbl(objspace, RCLASSEXT_CC_TBL(ext), iclass);
+}
+
#define TYPED_DATA_REFS_OFFSET_LIST(d) (size_t *)(uintptr_t)RTYPEDDATA_TYPE(d)->function.dmark
void
rb_gc_mark_children(void *objspace, VALUE obj)
{
+ struct gc_mark_classext_foreach_arg foreach_args;
+
if (FL_TEST_RAW(obj, FL_EXIVAR)) {
rb_mark_generic_ivar(obj);
}
@@ -2920,42 +3102,21 @@ rb_gc_mark_children(void *objspace, VALUE obj)
}
// Continue to the shared T_CLASS/T_MODULE
case T_MODULE:
- if (RCLASS_SUPER(obj)) {
- gc_mark_internal(RCLASS_SUPER(obj));
- }
+ foreach_args.objspace = objspace;
+ foreach_args.obj = obj;
+ rb_class_classext_foreach(obj, gc_mark_classext_module, (void *)&foreach_args);
- mark_m_tbl(objspace, RCLASS_M_TBL(obj));
- mark_cvc_tbl(objspace, obj);
- rb_cc_table_mark(obj);
- if (rb_shape_obj_too_complex_p(obj)) {
- gc_mark_tbl_no_pin((st_table *)RCLASS_FIELDS(obj));
- }
- else {
+ if (!rb_shape_obj_too_complex_p(obj)) {
for (attr_index_t i = 0; i < RCLASS_FIELDS_COUNT(obj); i++) {
- gc_mark_internal(RCLASS_FIELDS(obj)[i]);
+ gc_mark_internal(RCLASS_PRIME_FIELDS(obj)[i]);
}
}
-
- if (RCLASS_CONST_TBL(obj)) {
- rb_id_table_foreach_values(RCLASS_CONST_TBL(obj), mark_const_table_i, objspace);
- }
-
- gc_mark_internal(RCLASS_EXT(obj)->classpath);
break;
case T_ICLASS:
- if (RICLASS_OWNS_M_TBL_P(obj)) {
- mark_m_tbl(objspace, RCLASS_M_TBL(obj));
- }
- if (RCLASS_SUPER(obj)) {
- gc_mark_internal(RCLASS_SUPER(obj));
- }
-
- if (RCLASS_INCLUDER(obj)) {
- gc_mark_internal(RCLASS_INCLUDER(obj));
- }
- mark_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
- rb_cc_table_mark(obj);
+ foreach_args.objspace = objspace;
+ foreach_args.obj = obj;
+ rb_class_classext_foreach(obj, gc_mark_classext_iclass, (void *)&foreach_args);
break;
case T_ARRAY:
@@ -3031,8 +3192,8 @@ rb_gc_mark_children(void *objspace, VALUE obj)
VALUE klass = RBASIC_CLASS(obj);
// Increment max_iv_count if applicable, used to determine size pool allocation
- if (RCLASS_EXT(klass)->max_iv_count < fields_count) {
- RCLASS_EXT(klass)->max_iv_count = fields_count;
+ if (RCLASS_MAX_IV_COUNT(klass) < fields_count) {
+ RCLASS_WRITE_MAX_IV_COUNT(klass, fields_count);
}
}
@@ -3482,12 +3643,10 @@ update_cc_tbl_i(VALUE ccs_ptr, void *objspace)
}
static void
-update_cc_tbl(void *objspace, VALUE klass)
+update_cc_tbl(void *objspace, struct rb_id_table *tbl)
{
- struct rb_id_table *tbl = RCLASS_CC_TBL(klass);
- if (tbl) {
- rb_id_table_foreach_values(tbl, update_cc_tbl_i, objspace);
- }
+ if (!tbl) return;
+ rb_id_table_foreach_values(tbl, update_cc_tbl_i, objspace);
}
static enum rb_id_table_iterator_result
@@ -3507,16 +3666,14 @@ update_cvc_tbl_i(VALUE cvc_entry, void *objspace)
}
static void
-update_cvc_tbl(void *objspace, VALUE klass)
+update_cvc_tbl(void *objspace, struct rb_id_table *tbl)
{
- struct rb_id_table *tbl = RCLASS_CVC_TBL(klass);
- if (tbl) {
- rb_id_table_foreach_values(tbl, update_cvc_tbl_i, objspace);
- }
+ if (!tbl) return;
+ rb_id_table_foreach_values(tbl, update_cvc_tbl_i, objspace);
}
static enum rb_id_table_iterator_result
-update_const_table(VALUE value, void *objspace)
+update_const_tbl_i(VALUE value, void *objspace)
{
rb_const_entry_t *ce = (rb_const_entry_t *)value;
@@ -3535,35 +3692,93 @@ static void
update_const_tbl(void *objspace, struct rb_id_table *tbl)
{
if (!tbl) return;
- rb_id_table_foreach_values(tbl, update_const_table, objspace);
+ rb_id_table_foreach_values(tbl, update_const_tbl_i, objspace);
}
static void
-update_subclass_entries(void *objspace, rb_subclass_entry_t *entry)
+update_subclasses(void *objspace, rb_classext_t *ext)
{
+ rb_subclass_entry_t *entry;
+ rb_subclass_anchor_t *anchor = RCLASSEXT_SUBCLASSES(ext);
+ if (!anchor) return;
+ entry = anchor->head;
while (entry) {
- UPDATE_IF_MOVED(objspace, entry->klass);
+ if (entry->klass)
+ UPDATE_IF_MOVED(objspace, entry->klass);
entry = entry->next;
}
}
static void
-update_class_ext(void *objspace, rb_classext_t *ext)
+update_superclasses(rb_objspace_t *objspace, rb_classext_t *ext)
+{
+ size_t array_size = RCLASSEXT_SUPERCLASS_DEPTH(ext);
+ if (RCLASSEXT_SUPERCLASSES_OWNER(ext)) {
+ if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext))
+ array_size += 1;
+ for (size_t i = 0; i < array_size; i++) {
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_SUPERCLASSES(ext)[i]);
+ }
+ }
+}
+
+static void
+update_classext_values(rb_objspace_t *objspace, rb_classext_t *ext)
{
- UPDATE_IF_MOVED(objspace, ext->origin_);
- UPDATE_IF_MOVED(objspace, ext->includer);
- UPDATE_IF_MOVED(objspace, ext->refined_class);
- update_subclass_entries(objspace, ext->subclasses);
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_ORIGIN(ext));
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_REFINED_CLASS(ext));
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_INCLUDER(ext));
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_CLASSPATH(ext));
}
static void
-update_superclasses(void *objspace, VALUE obj)
+update_classext(rb_classext_t *ext, bool is_prime, VALUE namespace, void *arg)
{
- if (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
- for (size_t i = 0; i < RCLASS_SUPERCLASS_DEPTH(obj) + 1; i++) {
- UPDATE_IF_MOVED(objspace, RCLASS_SUPERCLASSES(obj)[i]);
+ struct classext_foreach_args *args = (struct classext_foreach_args *)arg;
+ VALUE klass = args->klass;
+ rb_objspace_t *objspace = args->objspace;
+
+ if (RCLASSEXT_SUPER(ext)) {
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_SUPER(ext));
+ }
+
+ update_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
+
+ if (args->obj_too_complex) {
+ gc_ref_update_table_values_only((st_table *)RCLASSEXT_FIELDS(ext));
+ } else {
+ // Classext is not copied in this case
+ for (attr_index_t i = 0; i < RCLASS_FIELDS_COUNT(klass); i++) {
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_FIELDS(RCLASS_EXT(klass))[i]);
}
}
+
+ if (!RCLASSEXT_SHARED_CONST_TBL(ext)) {
+ update_const_tbl(objspace, RCLASSEXT_CONST_TBL(ext));
+ }
+ update_cc_tbl(objspace, RCLASSEXT_CC_TBL(ext));
+ update_cvc_tbl(objspace, RCLASSEXT_CVC_TBL(ext));
+ update_superclasses(objspace, ext);
+ update_subclasses(objspace, ext);
+
+ update_classext_values(objspace, ext);
+}
+
+static void
+update_iclass_classext(rb_classext_t *ext, bool is_prime, VALUE namespace, void *arg)
+{
+ struct classext_foreach_args *args = (struct classext_foreach_args *)arg;
+ rb_objspace_t *objspace = args->objspace;
+
+ if (RCLASSEXT_SUPER(ext)) {
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_SUPER(ext));
+ }
+ update_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
+ update_m_tbl(objspace, RCLASSEXT_CALLABLE_M_TBL(ext));
+ update_cc_tbl(objspace, RCLASSEXT_CC_TBL(ext));
+ update_subclasses(objspace, ext);
+
+ update_classext_values(objspace, ext);
}
extern rb_symbols_t ruby_global_symbols;
@@ -3884,6 +4099,8 @@ rb_gc_update_vm_references(void *objspace)
void
rb_gc_update_object_references(void *objspace, VALUE obj)
{
+ struct classext_foreach_args args;
+
switch (BUILTIN_TYPE(obj)) {
case T_CLASS:
if (FL_TEST_RAW(obj, FL_SINGLETON)) {
@@ -3891,39 +4108,15 @@ rb_gc_update_object_references(void *objspace, VALUE obj)
}
// Continue to the shared T_CLASS/T_MODULE
case T_MODULE:
- if (RCLASS_SUPER((VALUE)obj)) {
- UPDATE_IF_MOVED(objspace, RCLASS(obj)->super);
- }
- update_m_tbl(objspace, RCLASS_M_TBL(obj));
- update_cc_tbl(objspace, obj);
- update_cvc_tbl(objspace, obj);
- update_superclasses(objspace, obj);
-
- if (rb_shape_obj_too_complex_p(obj)) {
- gc_ref_update_table_values_only(RCLASS_FIELDS_HASH(obj));
- }
- else {
- for (attr_index_t i = 0; i < RCLASS_FIELDS_COUNT(obj); i++) {
- UPDATE_IF_MOVED(objspace, RCLASS_FIELDS(obj)[i]);
- }
- }
-
- update_class_ext(objspace, RCLASS_EXT(obj));
- update_const_tbl(objspace, RCLASS_CONST_TBL(obj));
-
- UPDATE_IF_MOVED(objspace, RCLASS_EXT(obj)->classpath);
+ args.klass = obj;
+ args.obj_too_complex = rb_shape_obj_too_complex_p(obj);
+ args.objspace = objspace;
+ rb_class_classext_foreach(obj, update_classext, (void *)&args);
break;
case T_ICLASS:
- if (RICLASS_OWNS_M_TBL_P(obj)) {
- update_m_tbl(objspace, RCLASS_M_TBL(obj));
- }
- if (RCLASS_SUPER((VALUE)obj)) {
- UPDATE_IF_MOVED(objspace, RCLASS(obj)->super);
- }
- update_class_ext(objspace, RCLASS_EXT(obj));
- update_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
- update_cc_tbl(objspace, obj);
+ args.objspace = objspace;
+ rb_class_classext_foreach(obj, update_iclass_classext, (void *)&args);
break;
case T_IMEMO: