Skip to content

Commit 32ee3fa

Browse files
committed
Shink RClass when it is known they can't be namespaced
Even when namespaces are enabled, only a few core classes created during init will eventually be namespaced. For these it's OK to allocate a 320B slot to hold the extra namespace stuff. But for any class created post init, we know we'll never need the namespace and we can fit in a 160B slot.
1 parent ea4a53c commit 32ee3fa

File tree

2 files changed

+21
-10
lines changed

2 files changed

+21
-10
lines changed

class.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ class_classext_foreach_i(st_data_t key, st_data_t value, st_data_t arg)
394394
void
395395
rb_class_classext_foreach(VALUE klass, rb_class_classext_foreach_callback_func *func, void *arg)
396396
{
397-
st_table *tbl = RCLASS(klass)->ns_classext_tbl;
397+
st_table *tbl = RCLASS_CLASSEXT_TBL(klass);
398398
struct class_classext_foreach_arg foreach_arg;
399399
if (tbl) {
400400
foreach_arg.func = func;
@@ -649,7 +649,11 @@ class_alloc(enum ruby_value_type type, VALUE klass)
649649
rb_ns_subclasses_t *ns_subclasses;
650650
rb_subclass_anchor_t *anchor;
651651
const rb_namespace_t *ns = rb_definition_namespace();
652-
size_t alloc_size = sizeof(struct RClass) + sizeof(rb_classext_t);
652+
653+
size_t alloc_size = sizeof(struct RClass_and_rb_classext_t);
654+
if (!ruby_namespace_init_done) {
655+
alloc_size = sizeof(struct RClass_namespaceable);
656+
}
653657

654658
// class_alloc is supposed to return a new object that is not promoted yet.
655659
// So, we need to avoid GC after NEWOBJ_OF.

internal/class.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,24 +136,29 @@ STATIC_ASSERT(shape_max_variations, SHAPE_MAX_VARIATIONS < (1 << (sizeof(((rb_cl
136136

137137
struct RClass {
138138
struct RBasic basic;
139-
st_table *ns_classext_tbl; // ns_object -> (rb_classext_t *)
140139
VALUE object_id;
141140
/*
142141
* If ns_classext_tbl is NULL, then the prime classext is readable (because no other classext exists).
143142
* For the check whether writable or not, check flag RCLASS_PRIME_CLASSEXT_WRITABLE
144143
*/
145144
};
146145

147-
// Assert that classes can be embedded in heaps[2] (which has 160B slot size)
148-
// On 32bit platforms there is no variable width allocation so it doesn't matter.
149-
// TODO: restore this assertion after shrinking rb_classext_t
150-
// STATIC_ASSERT(sizeof_rb_classext_t, sizeof(struct RClass) + sizeof(rb_classext_t) <= 4 * RVALUE_SIZE || SIZEOF_VALUE < SIZEOF_LONG_LONG);
151-
152146
struct RClass_and_rb_classext_t {
153147
struct RClass rclass;
154148
rb_classext_t classext;
155149
};
156150

151+
#if SIZEOF_VALUE >= SIZEOF_LONG_LONG
152+
// Assert that classes can be embedded in heaps[2] (which has 160B slot size)
153+
// On 32bit platforms there is no variable width allocation so it doesn't matter.
154+
STATIC_ASSERT(sizeof_rb_classext_t, sizeof(struct RClass_and_rb_classext_t) <= 4 * RVALUE_SIZE);
155+
#endif
156+
157+
struct RClass_namespaceable {
158+
struct RClass_and_rb_classext_t base;
159+
st_table *ns_classext_tbl; // ns_object -> (rb_classext_t *)
160+
};
161+
157162
static const uint16_t RCLASS_MAX_SUPERCLASS_DEPTH = ((uint16_t)-1);
158163

159164
static inline bool RCLASS_SINGLETON_P(VALUE klass);
@@ -297,7 +302,8 @@ static inline st_table *
297302
RCLASS_CLASSEXT_TBL(VALUE klass)
298303
{
299304
if (FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE)) {
300-
return RCLASS(klass)->ns_classext_tbl;
305+
struct RClass_namespaceable *ns_klass = (struct RClass_namespaceable *)klass;
306+
return ns_klass->ns_classext_tbl;
301307
}
302308
return NULL;
303309
}
@@ -306,7 +312,8 @@ static inline void
306312
RCLASS_SET_CLASSEXT_TBL(VALUE klass, st_table *tbl)
307313
{
308314
RUBY_ASSERT(FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE));
309-
RCLASS(klass)->ns_classext_tbl = tbl;
315+
struct RClass_namespaceable *ns_klass = (struct RClass_namespaceable *)klass;
316+
ns_klass->ns_classext_tbl = tbl;
310317
}
311318

312319
/* class.c */

0 commit comments

Comments
 (0)