mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
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.
This commit is contained in:
parent
ea4a53c595
commit
32ee3fab0a
2 changed files with 21 additions and 10 deletions
8
class.c
8
class.c
|
@ -394,7 +394,7 @@ class_classext_foreach_i(st_data_t key, st_data_t value, st_data_t arg)
|
||||||
void
|
void
|
||||||
rb_class_classext_foreach(VALUE klass, rb_class_classext_foreach_callback_func *func, void *arg)
|
rb_class_classext_foreach(VALUE klass, rb_class_classext_foreach_callback_func *func, void *arg)
|
||||||
{
|
{
|
||||||
st_table *tbl = RCLASS(klass)->ns_classext_tbl;
|
st_table *tbl = RCLASS_CLASSEXT_TBL(klass);
|
||||||
struct class_classext_foreach_arg foreach_arg;
|
struct class_classext_foreach_arg foreach_arg;
|
||||||
if (tbl) {
|
if (tbl) {
|
||||||
foreach_arg.func = func;
|
foreach_arg.func = func;
|
||||||
|
@ -649,7 +649,11 @@ class_alloc(enum ruby_value_type type, VALUE klass)
|
||||||
rb_ns_subclasses_t *ns_subclasses;
|
rb_ns_subclasses_t *ns_subclasses;
|
||||||
rb_subclass_anchor_t *anchor;
|
rb_subclass_anchor_t *anchor;
|
||||||
const rb_namespace_t *ns = rb_definition_namespace();
|
const rb_namespace_t *ns = rb_definition_namespace();
|
||||||
size_t alloc_size = sizeof(struct RClass) + sizeof(rb_classext_t);
|
|
||||||
|
size_t alloc_size = sizeof(struct RClass_and_rb_classext_t);
|
||||||
|
if (!ruby_namespace_init_done) {
|
||||||
|
alloc_size = sizeof(struct RClass_namespaceable);
|
||||||
|
}
|
||||||
|
|
||||||
// class_alloc is supposed to return a new object that is not promoted yet.
|
// class_alloc is supposed to return a new object that is not promoted yet.
|
||||||
// So, we need to avoid GC after NEWOBJ_OF.
|
// So, we need to avoid GC after NEWOBJ_OF.
|
||||||
|
|
|
@ -136,7 +136,6 @@ STATIC_ASSERT(shape_max_variations, SHAPE_MAX_VARIATIONS < (1 << (sizeof(((rb_cl
|
||||||
|
|
||||||
struct RClass {
|
struct RClass {
|
||||||
struct RBasic basic;
|
struct RBasic basic;
|
||||||
st_table *ns_classext_tbl; // ns_object -> (rb_classext_t *)
|
|
||||||
VALUE object_id;
|
VALUE object_id;
|
||||||
/*
|
/*
|
||||||
* If ns_classext_tbl is NULL, then the prime classext is readable (because no other classext exists).
|
* If ns_classext_tbl is NULL, then the prime classext is readable (because no other classext exists).
|
||||||
|
@ -144,16 +143,22 @@ struct RClass {
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
// Assert that classes can be embedded in heaps[2] (which has 160B slot size)
|
|
||||||
// On 32bit platforms there is no variable width allocation so it doesn't matter.
|
|
||||||
// TODO: restore this assertion after shrinking rb_classext_t
|
|
||||||
// STATIC_ASSERT(sizeof_rb_classext_t, sizeof(struct RClass) + sizeof(rb_classext_t) <= 4 * RVALUE_SIZE || SIZEOF_VALUE < SIZEOF_LONG_LONG);
|
|
||||||
|
|
||||||
struct RClass_and_rb_classext_t {
|
struct RClass_and_rb_classext_t {
|
||||||
struct RClass rclass;
|
struct RClass rclass;
|
||||||
rb_classext_t classext;
|
rb_classext_t classext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if SIZEOF_VALUE >= SIZEOF_LONG_LONG
|
||||||
|
// Assert that classes can be embedded in heaps[2] (which has 160B slot size)
|
||||||
|
// On 32bit platforms there is no variable width allocation so it doesn't matter.
|
||||||
|
STATIC_ASSERT(sizeof_rb_classext_t, sizeof(struct RClass_and_rb_classext_t) <= 4 * RVALUE_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct RClass_namespaceable {
|
||||||
|
struct RClass_and_rb_classext_t base;
|
||||||
|
st_table *ns_classext_tbl; // ns_object -> (rb_classext_t *)
|
||||||
|
};
|
||||||
|
|
||||||
static const uint16_t RCLASS_MAX_SUPERCLASS_DEPTH = ((uint16_t)-1);
|
static const uint16_t RCLASS_MAX_SUPERCLASS_DEPTH = ((uint16_t)-1);
|
||||||
|
|
||||||
static inline bool RCLASS_SINGLETON_P(VALUE klass);
|
static inline bool RCLASS_SINGLETON_P(VALUE klass);
|
||||||
|
@ -297,7 +302,8 @@ static inline st_table *
|
||||||
RCLASS_CLASSEXT_TBL(VALUE klass)
|
RCLASS_CLASSEXT_TBL(VALUE klass)
|
||||||
{
|
{
|
||||||
if (FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE)) {
|
if (FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE)) {
|
||||||
return RCLASS(klass)->ns_classext_tbl;
|
struct RClass_namespaceable *ns_klass = (struct RClass_namespaceable *)klass;
|
||||||
|
return ns_klass->ns_classext_tbl;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -306,7 +312,8 @@ static inline void
|
||||||
RCLASS_SET_CLASSEXT_TBL(VALUE klass, st_table *tbl)
|
RCLASS_SET_CLASSEXT_TBL(VALUE klass, st_table *tbl)
|
||||||
{
|
{
|
||||||
RUBY_ASSERT(FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE));
|
RUBY_ASSERT(FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE));
|
||||||
RCLASS(klass)->ns_classext_tbl = tbl;
|
struct RClass_namespaceable *ns_klass = (struct RClass_namespaceable *)klass;
|
||||||
|
ns_klass->ns_classext_tbl = tbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* class.c */
|
/* class.c */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue