diff --git a/gc.c b/gc.c index 1b4a55fd9c5..e03d1362b84 100644 --- a/gc.c +++ b/gc.c @@ -1411,11 +1411,6 @@ rb_gc_obj_needs_cleanup_p(VALUE obj) return rb_gc_imemo_needs_cleanup_p(obj); } - shape_id_t shape_id = RBASIC_SHAPE_ID(obj); - if (rb_shape_has_fields(shape_id) && rb_shape_layout(shape_id) == SHAPE_ID_LAYOUT_OTHER) { - return true; - } - switch (flags & RUBY_T_MASK) { case T_FLOAT: case T_RATIONAL: @@ -2162,10 +2157,6 @@ rb_gc_obj_free_vm_weak_references(VALUE obj) { ASSUME(!RB_SPECIAL_CONST_P(obj)); - if (rb_obj_gen_fields_p(obj)) { - rb_free_generic_ivar(obj); - } - switch (BUILTIN_TYPE(obj)) { case T_STRING: if (FL_TEST_RAW(obj, RSTRING_FSTR)) { @@ -4048,6 +4039,20 @@ vm_weak_table_frozen_strings_foreach(VALUE *str, void *data) } void rb_fstring_foreach_with_replace(int (*callback)(VALUE *str, void *data), void *data); + +// Whether this table must be cleaned every GC after marking. +// Other tables may be skipped cleaned up per-object via rb_gc_obj_free_vm_weak_references. +bool +rb_gc_vm_weak_table_essential_p(enum rb_gc_vm_weak_tables table) +{ + switch (table) { + case RB_GC_VM_GENERIC_FIELDS_TABLE: + return true; + default: + return false; + } +} + void rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback, vm_table_update_callback_func update_callback, diff --git a/gc/default/default.c b/gc/default/default.c index cee550df6b6..e4889a007a1 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -4232,6 +4232,15 @@ gc_sweep_freeobj_hooks(rb_objspace_t *objspace) } } +static int +gc_sweep_weak_table_i(VALUE val, void *data) +{ + rb_objspace_t *objspace = data; + if (RB_SPECIAL_CONST_P(val)) return ST_CONTINUE; + if (RVALUE_MARKED(objspace, val)) return ST_CONTINUE; + return ST_DELETE; +} + static void gc_sweep_start(rb_objspace_t *objspace) { @@ -4242,6 +4251,17 @@ gc_sweep_start(rb_objspace_t *objspace) gc_sweep_freeobj_hooks(objspace); } + for (int table = 0; table < RB_GC_VM_WEAK_TABLE_COUNT; table++) { + if (!rb_gc_vm_weak_table_essential_p(table)) continue; + rb_gc_vm_weak_table_foreach( + gc_sweep_weak_table_i, + NULL, + objspace, + true, + table + ); + } + #if GC_CAN_COMPILE_COMPACTION if (objspace->flags.during_compacting) { gc_sort_heap_by_compare_func( diff --git a/gc/gc.h b/gc/gc.h index 3de9b3f165d..7ab14af1a58 100644 --- a/gc/gc.h +++ b/gc/gc.h @@ -92,6 +92,7 @@ MODULAR_GC_FN void rb_gc_vm_unlock_no_barrier(unsigned int lev, const char *file MODULAR_GC_FN void rb_gc_vm_barrier(void); MODULAR_GC_FN size_t rb_gc_obj_optimal_size(VALUE obj); MODULAR_GC_FN void rb_gc_mark_children(void *objspace, VALUE obj); +MODULAR_GC_FN bool rb_gc_vm_weak_table_essential_p(enum rb_gc_vm_weak_tables table); MODULAR_GC_FN void rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback, vm_table_update_callback_func update_callback, void *data, bool weak_only, enum rb_gc_vm_weak_tables table); MODULAR_GC_FN void rb_gc_update_object_references(void *objspace, VALUE obj); MODULAR_GC_FN void rb_gc_update_vm_references(void *objspace);