summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--class.c46
-rw-r--r--eval.c3
-rw-r--r--include/ruby/internal/core/rclass.h2
-rw-r--r--internal/class.h12
-rw-r--r--object.c4
-rw-r--r--yjit/src/cruby_bindings.inc.rs2
-rw-r--r--zjit/src/cruby_bindings.inc.rs2
7 files changed, 41 insertions, 30 deletions
diff --git a/class.c b/class.c
index b984dcb137..43ccb75de1 100644
--- a/class.c
+++ b/class.c
@@ -42,6 +42,8 @@
* 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE
* This class's prime classext is the only classext and writable from any namespaces.
* If unset, the prime classext is writable only from the root namespace.
+ * 3: RCLASS_IS_INITIALIZED
+ * Class has been initialized.
*/
/* Flags of T_ICLASS
@@ -56,13 +58,13 @@
* 0: RCLASS_IS_ROOT
* The class has been added to the VM roots. Will always be marked and pinned.
* This is done for classes defined from C to allow storing them in global variables.
- * 1: RMODULE_ALLOCATED_BUT_NOT_INITIALIZED
- * Module has not been initialized.
+ * 1: RMODULE_IS_REFINEMENT
+ * Module is used for refinements.
* 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE
* This module's prime classext is the only classext and writable from any namespaces.
* If unset, the prime classext is writable only from the root namespace.
- * 3: RMODULE_IS_REFINEMENT
- * Module is used for refinements.
+ * 3: RCLASS_IS_INITIALIZED
+ * Module has been initialized.
*/
#define METACLASS_OF(k) RBASIC(k)->klass
@@ -746,6 +748,9 @@ rb_class_boot(VALUE super)
class_initialize_method_table(klass);
class_associate_super(klass, super, true);
+ if (super && !UNDEF_P(super)) {
+ rb_class_set_initialized(klass);
+ }
return (VALUE)klass;
}
@@ -903,7 +908,7 @@ class_init_copy_check(VALUE clone, VALUE orig)
if (orig == rb_cBasicObject) {
rb_raise(rb_eTypeError, "can't copy the root class");
}
- if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
+ if (RCLASS_INITIALIZED_P(clone)) {
rb_raise(rb_eTypeError, "already initialized class");
}
if (RCLASS_SINGLETON_P(orig)) {
@@ -976,28 +981,18 @@ copy_tables(VALUE clone, VALUE orig)
static bool ensure_origin(VALUE klass);
-/**
- * If this flag is set, that module is allocated but not initialized yet.
- */
-enum {RMODULE_ALLOCATED_BUT_NOT_INITIALIZED = RUBY_FL_USER1};
-
-static inline bool
-RMODULE_UNINITIALIZED(VALUE module)
-{
- return FL_TEST_RAW(module, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
-}
-
void
-rb_module_set_initialized(VALUE mod)
+rb_class_set_initialized(VALUE klass)
{
- FL_UNSET_RAW(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
+ RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE));
+ FL_SET_RAW(klass, RCLASS_IS_INITIALIZED);
/* no more re-initialization */
}
void
rb_module_check_initializable(VALUE mod)
{
- if (!RMODULE_UNINITIALIZED(mod)) {
+ if (RCLASS_INITIALIZED_P(mod)) {
rb_raise(rb_eTypeError, "already initialized module");
}
}
@@ -1006,9 +1001,11 @@ rb_module_check_initializable(VALUE mod)
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
+ /* Only class or module is valid here, but other classes may enter here and
+ * only hit an exception on the OBJ_INIT_COPY checks
+ */
switch (BUILTIN_TYPE(clone)) {
case T_CLASS:
- case T_ICLASS:
class_init_copy_check(clone, orig);
break;
case T_MODULE:
@@ -1019,6 +1016,11 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
}
if (!OBJ_INIT_COPY(clone, orig)) return clone;
+ RUBY_ASSERT(RB_TYPE_P(orig, T_CLASS) || RB_TYPE_P(orig, T_MODULE));
+ RUBY_ASSERT(BUILTIN_TYPE(clone) == BUILTIN_TYPE(orig));
+
+ rb_class_set_initialized(clone);
+
/* cloned flag is refer at constant inline cache
* see vm_get_const_key_cref() in vm_insnhelper.c
*/
@@ -1266,6 +1268,7 @@ make_metaclass(VALUE klass)
super = RCLASS_SUPER(klass);
while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
class_associate_super(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass, true);
+ rb_class_set_initialized(klass);
// Full class ancestry may not have been filled until we reach here.
rb_class_update_superclasses(METACLASS_OF(metaclass));
@@ -1548,7 +1551,6 @@ rb_module_s_alloc(VALUE klass)
{
VALUE mod = class_alloc(T_MODULE, klass);
class_initialize_method_table(mod);
- FL_SET(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
return mod;
}
@@ -1672,7 +1674,7 @@ ensure_includable(VALUE klass, VALUE module)
{
rb_class_modify_check(klass);
Check_Type(module, T_MODULE);
- rb_module_set_initialized(module);
+ rb_class_set_initialized(module);
if (!NIL_P(rb_refinement_module_get_refined_class(module))) {
rb_raise(rb_eArgError, "refinement module is not allowed");
}
diff --git a/eval.c b/eval.c
index 739babf93d..c2fba6d984 100644
--- a/eval.c
+++ b/eval.c
@@ -422,7 +422,8 @@ rb_class_modify_check(VALUE klass)
Check_Type(klass, T_CLASS);
}
if (RB_TYPE_P(klass, T_MODULE)) {
- rb_module_set_initialized(klass);
+ // TODO: shouldn't this only happen in a few places?
+ rb_class_set_initialized(klass);
}
if (OBJ_FROZEN(klass)) {
const char *desc;
diff --git a/include/ruby/internal/core/rclass.h b/include/ruby/internal/core/rclass.h
index b0b6bfc80c..6f78cc569b 100644
--- a/include/ruby/internal/core/rclass.h
+++ b/include/ruby/internal/core/rclass.h
@@ -58,7 +58,7 @@ enum ruby_rmodule_flags {
* rb_mod_refine() has this flag set. This is the bit which controls
* difference between normal inclusion versus refinements.
*/
- RMODULE_IS_REFINEMENT = RUBY_FL_USER3
+ RMODULE_IS_REFINEMENT = RUBY_FL_USER1
};
struct RClass; /* Opaque, declared here for RCLASS() macro. */
diff --git a/internal/class.h b/internal/class.h
index 406f0a30cb..0e6506d739 100644
--- a/internal/class.h
+++ b/internal/class.h
@@ -294,8 +294,9 @@ static inline void RCLASS_SET_CLASSPATH(VALUE klass, VALUE classpath, bool perma
static inline void RCLASS_WRITE_CLASSPATH(VALUE klass, VALUE classpath, bool permanent);
#define RCLASS_IS_ROOT FL_USER0
-// 1 is for RUBY_FL_SINGLETON or RMODULE_ALLOCATED_BUT_NOT_INITIALIZED (see class.c)
+// 1 is for RUBY_FL_SINGLETON or RMODULE_IS_REFINEMENT
#define RCLASS_PRIME_CLASSEXT_WRITABLE FL_USER2
+#define RCLASS_IS_INITIALIZED FL_USER3
// 3 is RMODULE_IS_REFINEMENT for RMODULE
// 4-19: SHAPE_FLAG_MASK
@@ -485,7 +486,7 @@ VALUE rb_class_set_super(VALUE klass, VALUE super);
VALUE rb_class_boot(VALUE);
VALUE rb_class_s_alloc(VALUE klass);
VALUE rb_module_s_alloc(VALUE klass);
-void rb_module_set_initialized(VALUE module);
+void rb_class_set_initialized(VALUE klass);
void rb_module_check_initializable(VALUE module);
VALUE rb_make_metaclass(VALUE, VALUE);
VALUE rb_include_class_new(VALUE, VALUE);
@@ -796,4 +797,11 @@ RCLASS_SET_CLONED(VALUE klass, bool cloned)
RCLASSEXT_CLONED(RCLASS_EXT_PRIME(klass)) = cloned;
}
+static inline bool
+RCLASS_INITIALIZED_P(VALUE klass)
+{
+ VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE));
+ return FL_TEST_RAW(klass, RCLASS_IS_INITIALIZED);
+}
+
#endif /* INTERNAL_CLASS_H */
diff --git a/object.c b/object.c
index 5e5329a5f8..9bd1d96e9f 100644
--- a/object.c
+++ b/object.c
@@ -2069,7 +2069,7 @@ rb_class_initialize(int argc, VALUE *argv, VALUE klass)
else {
super = argv[0];
rb_check_inheritable(super);
- if (super != rb_cBasicObject && !RCLASS_SUPER(super)) {
+ if (!RCLASS_INITIALIZED_P(super)) {
rb_raise(rb_eTypeError, "can't inherit uninitialized class");
}
}
@@ -2126,7 +2126,7 @@ class_get_alloc_func(VALUE klass)
{
rb_alloc_func_t allocator;
- if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) {
+ if (!RCLASS_INITIALIZED_P(klass)) {
rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
}
if (RCLASS_SINGLETON_P(klass)) {
diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs
index b0dd348aa6..4e56272eed 100644
--- a/yjit/src/cruby_bindings.inc.rs
+++ b/yjit/src/cruby_bindings.inc.rs
@@ -303,7 +303,7 @@ pub const RARRAY_EMBED_LEN_MASK: ruby_rarray_flags = 4161536;
pub type ruby_rarray_flags = u32;
pub const RARRAY_EMBED_LEN_SHIFT: ruby_rarray_consts = 15;
pub type ruby_rarray_consts = u32;
-pub const RMODULE_IS_REFINEMENT: ruby_rmodule_flags = 32768;
+pub const RMODULE_IS_REFINEMENT: ruby_rmodule_flags = 8192;
pub type ruby_rmodule_flags = u32;
pub const ROBJECT_EMBED: ruby_robject_flags = 8192;
pub type ruby_robject_flags = u32;
diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs
index aebeee226e..ab6db40efb 100644
--- a/zjit/src/cruby_bindings.inc.rs
+++ b/zjit/src/cruby_bindings.inc.rs
@@ -152,7 +152,7 @@ pub const RARRAY_EMBED_LEN_MASK: ruby_rarray_flags = 4161536;
pub type ruby_rarray_flags = u32;
pub const RARRAY_EMBED_LEN_SHIFT: ruby_rarray_consts = 15;
pub type ruby_rarray_consts = u32;
-pub const RMODULE_IS_REFINEMENT: ruby_rmodule_flags = 32768;
+pub const RMODULE_IS_REFINEMENT: ruby_rmodule_flags = 8192;
pub type ruby_rmodule_flags = u32;
pub const ROBJECT_EMBED: ruby_robject_flags = 8192;
pub type ruby_robject_flags = u32;