From 19f331f58823dc0ff90ba7806c46380dc4064fa3 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Sat, 26 Feb 2022 16:05:06 -0800 Subject: Dedup superclass array in leaf sibling classes Previously, we would build a new `superclasses` array for each class, even though for all immediate subclasses of a class, the array is identical. This avoids duplicating the arrays on leaf classes (those without subclasses) by calculating and storing a "superclasses including self" array on a class when it's first inherited and sharing that among all superclasses. An additional trick used is that the "superclass array including self" is valid as "self"'s superclass array. It just has it's own class at the end. We can use this to avoid an extra pointer of storage and can use one bit of a flag to track that we've "upgraded" the array. --- class.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'class.c') diff --git a/class.c b/class.c index ef3f8aac2e..0acac96022 100644 --- a/class.c +++ b/class.c @@ -259,17 +259,21 @@ rb_class_boot(VALUE super) return (VALUE)klass; } -void -rb_class_remove_superclasses(VALUE klass) +static VALUE * +class_superclasses_including_self(VALUE klass) { - if (!RB_TYPE_P(klass, T_CLASS)) - return; + if (FL_TEST_RAW(klass, RCLASS_SUPERCLASSES_INCLUDE_SELF)) + return RCLASS_SUPERCLASSES(klass); - if (RCLASS_SUPERCLASSES(klass)) - xfree(RCLASS_SUPERCLASSES(klass)); + size_t depth = RCLASS_SUPERCLASS_DEPTH(klass); + VALUE *superclasses = xmalloc(sizeof(VALUE) * (depth + 1)); + if (depth > 0) + memcpy(superclasses, RCLASS_SUPERCLASSES(klass), sizeof(VALUE) * depth); + superclasses[depth] = klass; - RCLASS_SUPERCLASSES(klass) = NULL; - RCLASS_SUPERCLASS_DEPTH(klass) = 0; + RCLASS_SUPERCLASSES(klass) = superclasses; + FL_SET_RAW(klass, RCLASS_SUPERCLASSES_INCLUDE_SELF); + return superclasses; } void @@ -303,17 +307,8 @@ rb_class_update_superclasses(VALUE klass) return; } - size_t parent_num = RCLASS_SUPERCLASS_DEPTH(super); - size_t num = parent_num + 1; - - VALUE *superclasses = xmalloc(sizeof(VALUE) * num); - superclasses[parent_num] = super; - if (parent_num > 0) { - memcpy(superclasses, RCLASS_SUPERCLASSES(super), sizeof(VALUE) * parent_num); - } - - RCLASS_SUPERCLASSES(klass) = superclasses; - RCLASS_SUPERCLASS_DEPTH(klass) = num; + RCLASS_SUPERCLASSES(klass) = class_superclasses_including_self(super); + RCLASS_SUPERCLASS_DEPTH(klass) = RCLASS_SUPERCLASS_DEPTH(super) + 1; } void -- cgit v1.2.1