diff options
author | Satoshi Tagomori <[email protected]> | 2025-04-30 13:48:02 +0900 |
---|---|---|
committer | Satoshi Tagomori <[email protected]> | 2025-05-11 23:32:50 +0900 |
commit | 382645d440d5da66a0c04557f3ff2ca226de3a27 (patch) | |
tree | b7453449930197237e739d0985561b664f51b0f3 /gc.c | |
parent | 49742414f6444960838bb968bab43db27f5872c1 (diff) |
namespace on read
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 527 |
1 files changed, 360 insertions, 167 deletions
@@ -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: |