Don't use namespaced classext for superclasses

Superclasses can't be modified by user code, so do not need namespace
indirection. For example Object.superclass is always BasicObject, no
matter what modules are included onto it.
This commit is contained in:
John Hawthorn 2025-05-20 13:10:41 -07:00
parent 1435ea7f44
commit 11ad7f5f47
Notes: git 2025-05-23 17:22:38 +00:00
3 changed files with 17 additions and 33 deletions

17
class.c
View File

@ -183,16 +183,6 @@ duplicate_classext_const_tbl(struct rb_id_table *src, VALUE klass)
return dst;
}
static void
duplicate_classext_superclasses(rb_classext_t *orig, rb_classext_t *copy)
{
RCLASSEXT_SUPERCLASSES(copy) = RCLASSEXT_SUPERCLASSES(orig);
RCLASSEXT_SUPERCLASS_DEPTH(copy) = RCLASSEXT_SUPERCLASS_DEPTH(orig);
// the copy is always not the owner and the orig (or its parent class) will maintain the superclasses array
RCLASSEXT_SUPERCLASSES_OWNER(copy) = false;
RCLASSEXT_SUPERCLASSES_WITH_SELF(copy) = RCLASSEXT_SUPERCLASSES_WITH_SELF(orig);
}
static VALUE
namespace_subclasses_tbl_key(const rb_namespace_t *ns)
{
@ -349,9 +339,6 @@ rb_class_duplicate_classext(rb_classext_t *orig, VALUE klass, const rb_namespace
RCLASSEXT_CVC_TBL(ext) = duplicate_classext_id_table(RCLASSEXT_CVC_TBL(orig), dup_iclass);
// superclass_depth, superclasses
duplicate_classext_superclasses(orig, ext);
// subclasses, subclasses_index
duplicate_classext_subclasses(orig, ext);
@ -832,11 +819,11 @@ rb_class_update_superclasses(VALUE klass)
}
else {
superclasses = class_superclasses_including_self(super);
RCLASS_WRITE_SUPERCLASSES(super, super_depth, superclasses, true, true);
RCLASS_WRITE_SUPERCLASSES(super, super_depth, superclasses, true);
}
size_t depth = super_depth == RCLASS_MAX_SUPERCLASS_DEPTH ? super_depth : super_depth + 1;
RCLASS_WRITE_SUPERCLASSES(klass, depth, superclasses, false, false);
RCLASS_WRITE_SUPERCLASSES(klass, depth, superclasses, false);
}
void

16
gc.c
View File

@ -1238,7 +1238,8 @@ classext_free(rb_classext_t *ext, bool is_prime, VALUE namespace, void *arg)
rb_id_table_free(tbl);
}
rb_class_classext_free_subclasses(ext, args->klass);
if (RCLASSEXT_SUPERCLASSES_OWNER(ext)) {
if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) {
RUBY_ASSERT(is_prime); // superclasses should only be used on prime
xfree(RCLASSEXT_SUPERCLASSES(ext));
}
if (!is_prime) { // the prime classext will be freed with RClass
@ -2293,10 +2294,9 @@ classext_superclasses_memsize(rb_classext_t *ext, bool prime, VALUE namespace, v
{
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;
if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) {
RUBY_ASSERT(prime);
array_size = RCLASSEXT_SUPERCLASS_DEPTH(ext) + 1;
*size += array_size * sizeof(VALUE);
}
}
@ -3802,10 +3802,8 @@ update_subclasses(void *objspace, rb_classext_t *ext)
static void
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;
if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) {
size_t array_size = RCLASSEXT_SUPERCLASS_DEPTH(ext) + 1;
for (size_t i = 0; i < array_size; i++) {
UPDATE_IF_MOVED(objspace, RCLASSEXT_SUPERCLASSES(ext)[i]);
}

View File

@ -127,7 +127,6 @@ struct rb_classext_struct {
bool shared_const_tbl : 1;
bool iclass_is_origin : 1;
bool iclass_origin_shared_mtbl : 1;
bool superclasses_owner : 1;
bool superclasses_with_self : 1;
VALUE classpath;
};
@ -198,7 +197,6 @@ static inline rb_classext_t * RCLASS_EXT_WRITABLE(VALUE obj);
#define RCLASSEXT_SHARED_CONST_TBL(ext) (ext->shared_const_tbl)
#define RCLASSEXT_ICLASS_IS_ORIGIN(ext) (ext->iclass_is_origin)
#define RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext) (ext->iclass_origin_shared_mtbl)
#define RCLASSEXT_SUPERCLASSES_OWNER(ext) (ext->superclasses_owner)
#define RCLASSEXT_SUPERCLASSES_WITH_SELF(ext) (ext->superclasses_with_self)
#define RCLASSEXT_CLASSPATH(ext) (ext->classpath)
@ -227,9 +225,6 @@ static inline void RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE
* so always those should be writable.
*/
#define RCLASS_CVC_TBL(c) (RCLASS_EXT_READABLE(c)->cvc_tbl)
#define RCLASS_SUPERCLASS_DEPTH(c) (RCLASS_EXT_READABLE(c)->superclass_depth)
#define RCLASS_SUPERCLASSES(c) (RCLASS_EXT_READABLE(c)->superclasses)
#define RCLASS_SUPERCLASSES_WITH_SELF_P(c) (RCLASS_EXT_READABLE(c)->superclasses_with_self)
#define RCLASS_SUBCLASSES_X(c) (RCLASS_EXT_READABLE(c)->subclasses)
#define RCLASS_SUBCLASSES_FIRST(c) (RCLASS_EXT_READABLE(c)->subclasses->head->next)
#define RCLASS_ORIGIN(c) (RCLASS_EXT_READABLE(c)->origin_)
@ -240,6 +235,11 @@ static inline void RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE
#define RCLASS_CLONED_P(c) (RCLASS_EXT_READABLE(c)->cloned)
#define RCLASS_CLASSPATH(c) (RCLASS_EXT_READABLE(c)->classpath)
// Superclasses can't be changed after initialization
#define RCLASS_SUPERCLASS_DEPTH(c) (RCLASS_EXT_PRIME(c)->superclass_depth)
#define RCLASS_SUPERCLASSES(c) (RCLASS_EXT_PRIME(c)->superclasses)
#define RCLASS_SUPERCLASSES_WITH_SELF_P(c) (RCLASS_EXT_PRIME(c)->superclasses_with_self)
// 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)
@ -270,7 +270,7 @@ static inline void RCLASS_WRITE_CC_TBL(VALUE klass, struct rb_id_table *table);
static inline void RCLASS_SET_CVC_TBL(VALUE klass, struct rb_id_table *table);
static inline void RCLASS_WRITE_CVC_TBL(VALUE klass, struct rb_id_table *table);
static inline void RCLASS_WRITE_SUPERCLASSES(VALUE klass, size_t depth, VALUE *superclasses, bool owns_it, bool with_self);
static inline void RCLASS_WRITE_SUPERCLASSES(VALUE klass, size_t depth, VALUE *superclasses, bool with_self);
static inline void RCLASS_SET_SUBCLASSES(VALUE klass, rb_subclass_anchor_t *anchor);
static inline void RCLASS_WRITE_NS_SUPER_SUBCLASSES(VALUE klass, rb_ns_subclasses_t *ns_subclasses);
static inline void RCLASS_WRITE_NS_MODULE_SUBCLASSES(VALUE klass, rb_ns_subclasses_t *ns_subclasses);
@ -714,14 +714,13 @@ RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass)
}
static inline void
RCLASS_WRITE_SUPERCLASSES(VALUE klass, size_t depth, VALUE *superclasses, bool owns_it, bool with_self)
RCLASS_WRITE_SUPERCLASSES(VALUE klass, size_t depth, VALUE *superclasses, bool with_self)
{
RUBY_ASSERT(depth <= RCLASS_MAX_SUPERCLASS_DEPTH);
rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass);
rb_classext_t *ext = RCLASS_EXT_PRIME(klass);
RCLASSEXT_SUPERCLASS_DEPTH(ext) = depth;
RCLASSEXT_SUPERCLASSES(ext) = superclasses;
RCLASSEXT_SUPERCLASSES_OWNER(ext) = owns_it;
RCLASSEXT_SUPERCLASSES_WITH_SELF(ext) = with_self;
}