Reclaim one VALUE from rb_classext_t

The `includer` field is only used for `T_ICLASS`, so by moving
it into the existing union we can save one `VALUE` per class
and module.
This commit is contained in:
Jean Boussier 2025-05-13 14:11:11 +02:00
parent c941fced21
commit 2ca8769443
Notes: git 2025-05-13 12:55:51 +00:00
2 changed files with 14 additions and 8 deletions

10
gc.c
View File

@ -3718,12 +3718,14 @@ update_superclasses(rb_objspace_t *objspace, rb_classext_t *ext)
}
static void
update_classext_values(rb_objspace_t *objspace, rb_classext_t *ext)
update_classext_values(rb_objspace_t *objspace, rb_classext_t *ext, bool is_iclass)
{
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));
if (is_iclass) {
UPDATE_IF_MOVED(objspace, RCLASSEXT_INCLUDER(ext));
}
}
static void
@ -3757,7 +3759,7 @@ update_classext(rb_classext_t *ext, bool is_prime, VALUE namespace, void *arg)
update_superclasses(objspace, ext);
update_subclasses(objspace, ext);
update_classext_values(objspace, ext);
update_classext_values(objspace, ext, false);
}
static void
@ -3774,7 +3776,7 @@ update_iclass_classext(rb_classext_t *ext, bool is_prime, VALUE namespace, void
update_cc_tbl(objspace, RCLASSEXT_CC_TBL(ext));
update_subclasses(objspace, ext);
update_classext_values(objspace, ext);
update_classext_values(objspace, ext, true);
}
extern rb_symbols_t ruby_global_symbols;

View File

@ -116,8 +116,10 @@ struct rb_classext_struct {
struct {
VALUE attached_object;
} singleton_class;
struct {
const VALUE includer;
} iclass;
} as;
const VALUE includer;
attr_index_t max_iv_count;
unsigned char variation_count;
bool permanent_classpath : 1;
@ -184,7 +186,7 @@ static inline rb_classext_t * RCLASS_EXT_WRITABLE(VALUE obj);
#define RCLASSEXT_ORIGIN(ext) (ext->origin_)
#define RCLASSEXT_REFINED_CLASS(ext) (ext->refined_class)
// class.allocator/singleton_class.attached_object are not accessed directly via RCLASSEXT_*
#define RCLASSEXT_INCLUDER(ext) (ext->includer)
#define RCLASSEXT_INCLUDER(ext) (ext->as.iclass.includer)
#define RCLASSEXT_MAX_IV_COUNT(ext) (ext->max_iv_count)
#define RCLASSEXT_VARIATION_COUNT(ext) (ext->variation_count)
#define RCLASSEXT_PERMANENT_CLASSPATH(ext) (ext->permanent_classpath)
@ -237,7 +239,7 @@ static inline void RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE
// namespaces don't make changes on these refined_class/attached_object/includer
#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT_PRIME(c)->refined_class)
#define RCLASS_ATTACHED_OBJECT(c) (RCLASS_EXT_PRIME(c)->as.singleton_class.attached_object)
#define RCLASS_INCLUDER(c) (RCLASS_EXT_PRIME(c)->includer)
#define RCLASS_INCLUDER(c) (RCLASS_EXT_PRIME(c)->as.iclass.includer)
// Writable classext entries (instead of RCLASS_SET_*) because member data will be operated directly
#define RCLASS_WRITABLE_M_TBL(c) (RCLASS_EXT_WRITABLE(c)->m_tbl)
@ -459,6 +461,7 @@ RCLASSEXT_SET_ORIGIN(rb_classext_t *ext, VALUE klass, VALUE origin)
static inline void
RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE includer)
{
RUBY_ASSERT(RB_TYPE_P(klass, T_ICLASS));
RB_OBJ_WRITE(klass, &(RCLASSEXT_INCLUDER(ext)), includer);
}
@ -651,7 +654,7 @@ RCLASS_SET_REFINED_CLASS(VALUE klass, VALUE refined)
static inline rb_alloc_func_t
RCLASS_ALLOCATOR(VALUE klass)
{
if (RCLASS_SINGLETON_P(klass)) {
if (RCLASS_SINGLETON_P(klass) || RB_TYPE_P(klass, T_ICLASS)) {
return 0;
}
return RCLASS_EXT_PRIME(klass)->as.class.allocator;
@ -702,6 +705,7 @@ RICLASS_OWNS_M_TBL_P(VALUE iclass)
static inline void
RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass)
{
RUBY_ASSERT(RB_TYPE_P(iclass, T_ICLASS));
RB_OBJ_WRITE(iclass, &RCLASS_INCLUDER(iclass), klass);
}