Make refinement module iclass cache a WeakMap

Previously, creating and using an arbitrary number of refinements in
a loop would result in a memory leak, since the refinement module
iclass cache would keep a reference to the refinement, preventing it
from being GCed. This switches from using a hash to using a WeakMap
to prevent the memory leak.
This commit is contained in:
Jeremy Evans committed 2026-10-10 01:14:57 -07:00
1 parent 35c32429e1
commit 7ecfc98f31
1 file changed
+8 -8
Notes: git 2026-10-10 08:16:15 +00:00
+8 -8
View File
@@ -4641,27 +4641,27 @@ refined_method_callable_without_refinement(const rb_callable_method_entry_t *me)
}
// Construct correct super chain for module refinements.
// Each class including/prepending a module has a hash mapping refinement
// modules to refinement module iclasses with the correct super. Like
// singleton classes, these are lazily initialized (both the hash and
// Each class including/prepending a module has a weak map mapping refinement
// iclasses to refinement module iclasses with the correct super. Like
// singleton classes, these are lazily initialized (both the map and
// the refinement module iclasses).
static VALUE
module_refinement_iclass(VALUE refinement_iclass, VALUE defined_class)
{
VALUE module_ref_iclass = Qnil;
VALUE module_ref_iclass = Qundef;
RB_VM_LOCKING() {
VALUE cache = RCLASS_MODULE_REFINEMENT_ICLASSES(defined_class);
if (LIKELY(cache)) {
module_ref_iclass = rb_hash_lookup(cache, refinement_iclass);
module_ref_iclass = rb_wmap_lookup(cache, refinement_iclass);
}
else {
cache = rb_obj_hide(rb_ident_hash_new());
cache = rb_wmap_new_hidden();
RCLASS_SET_MODULE_REFINEMENT_ICLASSES(defined_class, cache);
}
if (NIL_P(module_ref_iclass)) {
if (UNDEF_P(module_ref_iclass)) {
VALUE super;
VALUE refinement_iclass_super = RCLASS_SUPER(refinement_iclass);
@@ -4675,7 +4675,7 @@ module_refinement_iclass(VALUE refinement_iclass, VALUE defined_class)
module_ref_iclass = rb_include_class_new(RBASIC(refinement_iclass)->klass, super);
RCLASS_SET_REFINED_CLASS(module_ref_iclass, RCLASS_REFINED_CLASS(refinement_iclass));
rb_class_subclass_add(RCLASS_REFINED_CLASS(refinement_iclass), module_ref_iclass);
rb_hash_aset(cache, refinement_iclass, module_ref_iclass);
rb_wmap_aset(cache, refinement_iclass, module_ref_iclass);
}
}