mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
Allocate singleton classes as namespaceable if their parent are
This commit is contained in:
parent
32ee3fab0a
commit
c6dd07d66f
1 changed files with 34 additions and 18 deletions
52
class.c
52
class.c
|
@ -644,14 +644,18 @@ class_switch_superclass(VALUE super, VALUE klass)
|
||||||
* @note this function is not Class#allocate.
|
* @note this function is not Class#allocate.
|
||||||
*/
|
*/
|
||||||
static VALUE
|
static VALUE
|
||||||
class_alloc(enum ruby_value_type type, VALUE klass)
|
class_alloc0(enum ruby_value_type type, VALUE klass, bool namespaceable)
|
||||||
{
|
{
|
||||||
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_and_rb_classext_t);
|
|
||||||
if (!ruby_namespace_init_done) {
|
if (!ruby_namespace_init_done) {
|
||||||
|
namespaceable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t alloc_size = sizeof(struct RClass_and_rb_classext_t);
|
||||||
|
if (namespaceable) {
|
||||||
alloc_size = sizeof(struct RClass_namespaceable);
|
alloc_size = sizeof(struct RClass_namespaceable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,7 +676,7 @@ class_alloc(enum ruby_value_type type, VALUE klass)
|
||||||
|
|
||||||
VALUE flags = type;
|
VALUE flags = type;
|
||||||
if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED;
|
if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED;
|
||||||
if (!ruby_namespace_init_done) flags |= RCLASS_NAMESPACEABLE;
|
if (namespaceable) flags |= RCLASS_NAMESPACEABLE;
|
||||||
|
|
||||||
NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size, 0);
|
NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size, 0);
|
||||||
|
|
||||||
|
@ -688,7 +692,7 @@ class_alloc(enum ruby_value_type type, VALUE klass)
|
||||||
RCLASS_PRIME_NS((VALUE)obj) = ns;
|
RCLASS_PRIME_NS((VALUE)obj) = ns;
|
||||||
// Classes/Modules defined in user namespaces are
|
// Classes/Modules defined in user namespaces are
|
||||||
// writable directly because it exists only in a namespace.
|
// writable directly because it exists only in a namespace.
|
||||||
RCLASS_SET_PRIME_CLASSEXT_WRITABLE((VALUE)obj, ruby_namespace_init_done || NAMESPACE_USER_P(ns));
|
RCLASS_SET_PRIME_CLASSEXT_WRITABLE((VALUE)obj, !namespaceable || NAMESPACE_USER_P(ns));
|
||||||
|
|
||||||
RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj);
|
RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj);
|
||||||
RCLASS_SET_REFINED_CLASS((VALUE)obj, Qnil);
|
RCLASS_SET_REFINED_CLASS((VALUE)obj, Qnil);
|
||||||
|
@ -698,6 +702,12 @@ class_alloc(enum ruby_value_type type, VALUE klass)
|
||||||
return (VALUE)obj;
|
return (VALUE)obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
class_alloc(enum ruby_value_type type, VALUE klass)
|
||||||
|
{
|
||||||
|
return class_alloc0(type, klass, false);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
class_associate_super(VALUE klass, VALUE super, bool init)
|
class_associate_super(VALUE klass, VALUE super, bool init)
|
||||||
{
|
{
|
||||||
|
@ -733,6 +743,23 @@ class_clear_method_table(VALUE c)
|
||||||
RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(c, rb_id_table_create(0));
|
RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(c, rb_id_table_create(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
class_boot_namespaceable(VALUE super, bool namespaceable)
|
||||||
|
{
|
||||||
|
VALUE klass = class_alloc0(T_CLASS, rb_cClass, namespaceable);
|
||||||
|
|
||||||
|
// initialize method table prior to class_associate_super()
|
||||||
|
// because class_associate_super() may cause GC and promote klass
|
||||||
|
class_initialize_method_table(klass);
|
||||||
|
|
||||||
|
class_associate_super(klass, super, true);
|
||||||
|
if (super && !UNDEF_P(super)) {
|
||||||
|
rb_class_set_initialized(klass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (VALUE)klass;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility function that wraps class_alloc.
|
* A utility function that wraps class_alloc.
|
||||||
*
|
*
|
||||||
|
@ -745,18 +772,7 @@ class_clear_method_table(VALUE c)
|
||||||
VALUE
|
VALUE
|
||||||
rb_class_boot(VALUE super)
|
rb_class_boot(VALUE super)
|
||||||
{
|
{
|
||||||
VALUE klass = class_alloc(T_CLASS, rb_cClass);
|
return class_boot_namespaceable(super, false);
|
||||||
|
|
||||||
// initialize method table prior to class_associate_super()
|
|
||||||
// because class_associate_super() may cause GC and promote klass
|
|
||||||
class_initialize_method_table(klass);
|
|
||||||
|
|
||||||
class_associate_super(klass, super, true);
|
|
||||||
if (super && !UNDEF_P(super)) {
|
|
||||||
rb_class_set_initialized(klass);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (VALUE)klass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE *
|
static VALUE *
|
||||||
|
@ -1254,7 +1270,7 @@ static inline VALUE
|
||||||
make_metaclass(VALUE klass)
|
make_metaclass(VALUE klass)
|
||||||
{
|
{
|
||||||
VALUE super;
|
VALUE super;
|
||||||
VALUE metaclass = rb_class_boot(Qundef);
|
VALUE metaclass = class_boot_namespaceable(Qundef, FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE));
|
||||||
|
|
||||||
FL_SET(metaclass, FL_SINGLETON);
|
FL_SET(metaclass, FL_SINGLETON);
|
||||||
rb_singleton_class_attached(metaclass, klass);
|
rb_singleton_class_attached(metaclass, klass);
|
||||||
|
@ -1290,7 +1306,7 @@ static inline VALUE
|
||||||
make_singleton_class(VALUE obj)
|
make_singleton_class(VALUE obj)
|
||||||
{
|
{
|
||||||
VALUE orig_class = METACLASS_OF(obj);
|
VALUE orig_class = METACLASS_OF(obj);
|
||||||
VALUE klass = rb_class_boot(orig_class);
|
VALUE klass = class_boot_namespaceable(orig_class, FL_TEST_RAW(orig_class, RCLASS_NAMESPACEABLE));
|
||||||
|
|
||||||
FL_SET(klass, FL_SINGLETON);
|
FL_SET(klass, FL_SINGLETON);
|
||||||
RBASIC_SET_CLASS(obj, klass);
|
RBASIC_SET_CLASS(obj, klass);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue