rb_gc_obj_needs_cleanup_p: skip sweep for most imemo/fields

There is only two rare cases where they need to be sweeped:

  - If they are so large that they're heap allocated.
  - If they have an object_id (and id2ref_tbl exist but
    we can't check that here)
This commit is contained in:
Jean Boussier 2026-04-08 13:10:50 +02:00
parent 30e3148825
commit 5cf6c842e5
Notes: git 2026-04-08 19:00:33 +00:00
2 changed files with 29 additions and 27 deletions

30
gc.c
View File

@ -1291,6 +1291,34 @@ rb_gc_handle_weak_references(VALUE obj)
}
}
static inline bool
rb_gc_imemo_needs_cleanup_p(VALUE obj)
{
switch (imemo_type(obj)) {
case imemo_constcache:
case imemo_cref:
case imemo_ifunc:
case imemo_memo:
case imemo_svar:
case imemo_callcache:
case imemo_throw_data:
return false;
case imemo_env:
case imemo_ment:
case imemo_iseq:
case imemo_callinfo:
return true;
case imemo_tmpbuf:
return ((rb_imemo_tmpbuf_t *)obj)->ptr != NULL;
case imemo_fields:
return FL_TEST_RAW(obj, OBJ_FIELD_HEAP) || (id2ref_tbl && rb_shape_obj_has_id(obj));
}
UNREACHABLE_RETURN(true);
}
/*
* Returns true if the object requires a full rb_gc_obj_free() call during sweep,
* false if it can be freed quickly without calling destructors or cleanup.
@ -1313,7 +1341,7 @@ rb_gc_obj_needs_cleanup_p(VALUE obj)
switch (flags & RUBY_T_MASK) {
case T_IMEMO:
return rb_imemo_needs_cleanup_p(obj);
return rb_gc_imemo_needs_cleanup_p(obj);
case T_DATA:
case T_OBJECT:

View File

@ -292,30 +292,4 @@ rb_imemo_fields_complex_tbl(VALUE fields_obj)
return IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table;
}
static inline bool
rb_imemo_needs_cleanup_p(VALUE obj)
{
switch (imemo_type(obj)) {
case imemo_constcache:
case imemo_cref:
case imemo_ifunc:
case imemo_memo:
case imemo_svar:
case imemo_callcache:
case imemo_throw_data:
return false;
case imemo_env:
case imemo_ment:
case imemo_iseq:
case imemo_callinfo:
case imemo_fields:
return true;
case imemo_tmpbuf:
return ((rb_imemo_tmpbuf_t *)obj)->ptr != NULL;
}
UNREACHABLE_RETURN(true);
}
#endif /* INTERNAL_IMEMO_H */