Skip to content

Commit c6dd07d

Browse files
committed
Allocate singleton classes as namespaceable if their parent are
1 parent 32ee3fa commit c6dd07d

File tree

1 file changed

+34
-18
lines changed

1 file changed

+34
-18
lines changed

class.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -644,14 +644,18 @@ class_switch_superclass(VALUE super, VALUE klass)
644644
* @note this function is not Class#allocate.
645645
*/
646646
static VALUE
647-
class_alloc(enum ruby_value_type type, VALUE klass)
647+
class_alloc0(enum ruby_value_type type, VALUE klass, bool namespaceable)
648648
{
649649
rb_ns_subclasses_t *ns_subclasses;
650650
rb_subclass_anchor_t *anchor;
651651
const rb_namespace_t *ns = rb_definition_namespace();
652652

653-
size_t alloc_size = sizeof(struct RClass_and_rb_classext_t);
654653
if (!ruby_namespace_init_done) {
654+
namespaceable = true;
655+
}
656+
657+
size_t alloc_size = sizeof(struct RClass_and_rb_classext_t);
658+
if (namespaceable) {
655659
alloc_size = sizeof(struct RClass_namespaceable);
656660
}
657661

@@ -672,7 +676,7 @@ class_alloc(enum ruby_value_type type, VALUE klass)
672676

673677
VALUE flags = type;
674678
if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED;
675-
if (!ruby_namespace_init_done) flags |= RCLASS_NAMESPACEABLE;
679+
if (namespaceable) flags |= RCLASS_NAMESPACEABLE;
676680

677681
NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size, 0);
678682

@@ -688,7 +692,7 @@ class_alloc(enum ruby_value_type type, VALUE klass)
688692
RCLASS_PRIME_NS((VALUE)obj) = ns;
689693
// Classes/Modules defined in user namespaces are
690694
// writable directly because it exists only in a namespace.
691-
RCLASS_SET_PRIME_CLASSEXT_WRITABLE((VALUE)obj, ruby_namespace_init_done || NAMESPACE_USER_P(ns));
695+
RCLASS_SET_PRIME_CLASSEXT_WRITABLE((VALUE)obj, !namespaceable || NAMESPACE_USER_P(ns));
692696

693697
RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj);
694698
RCLASS_SET_REFINED_CLASS((VALUE)obj, Qnil);
@@ -698,6 +702,12 @@ class_alloc(enum ruby_value_type type, VALUE klass)
698702
return (VALUE)obj;
699703
}
700704

705+
static VALUE
706+
class_alloc(enum ruby_value_type type, VALUE klass)
707+
{
708+
return class_alloc0(type, klass, false);
709+
}
710+
701711
static VALUE
702712
class_associate_super(VALUE klass, VALUE super, bool init)
703713
{
@@ -733,19 +743,10 @@ class_clear_method_table(VALUE c)
733743
RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(c, rb_id_table_create(0));
734744
}
735745

736-
/**
737-
* A utility function that wraps class_alloc.
738-
*
739-
* allocates a class and initializes safely.
740-
* @param super a class from which the new class derives.
741-
* @return a class object.
742-
* @pre `super` must be a class.
743-
* @post the metaclass of the new class is Class.
744-
*/
745-
VALUE
746-
rb_class_boot(VALUE super)
746+
static VALUE
747+
class_boot_namespaceable(VALUE super, bool namespaceable)
747748
{
748-
VALUE klass = class_alloc(T_CLASS, rb_cClass);
749+
VALUE klass = class_alloc0(T_CLASS, rb_cClass, namespaceable);
749750

750751
// initialize method table prior to class_associate_super()
751752
// because class_associate_super() may cause GC and promote klass
@@ -759,6 +760,21 @@ rb_class_boot(VALUE super)
759760
return (VALUE)klass;
760761
}
761762

763+
/**
764+
* A utility function that wraps class_alloc.
765+
*
766+
* allocates a class and initializes safely.
767+
* @param super a class from which the new class derives.
768+
* @return a class object.
769+
* @pre `super` must be a class.
770+
* @post the metaclass of the new class is Class.
771+
*/
772+
VALUE
773+
rb_class_boot(VALUE super)
774+
{
775+
return class_boot_namespaceable(super, false);
776+
}
777+
762778
static VALUE *
763779
class_superclasses_including_self(VALUE klass)
764780
{
@@ -1254,7 +1270,7 @@ static inline VALUE
12541270
make_metaclass(VALUE klass)
12551271
{
12561272
VALUE super;
1257-
VALUE metaclass = rb_class_boot(Qundef);
1273+
VALUE metaclass = class_boot_namespaceable(Qundef, FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE));
12581274

12591275
FL_SET(metaclass, FL_SINGLETON);
12601276
rb_singleton_class_attached(metaclass, klass);
@@ -1290,7 +1306,7 @@ static inline VALUE
12901306
make_singleton_class(VALUE obj)
12911307
{
12921308
VALUE orig_class = METACLASS_OF(obj);
1293-
VALUE klass = rb_class_boot(orig_class);
1309+
VALUE klass = class_boot_namespaceable(orig_class, FL_TEST_RAW(orig_class, RCLASS_NAMESPACEABLE));
12941310

12951311
FL_SET(klass, FL_SINGLETON);
12961312
RBASIC_SET_CLASS(obj, klass);

0 commit comments

Comments
 (0)