diff options
-rw-r--r-- | class.c | 46 | ||||
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | include/ruby/internal/core/rclass.h | 2 | ||||
-rw-r--r-- | internal/class.h | 12 | ||||
-rw-r--r-- | object.c | 4 | ||||
-rw-r--r-- | yjit/src/cruby_bindings.inc.rs | 2 | ||||
-rw-r--r-- | zjit/src/cruby_bindings.inc.rs | 2 |
7 files changed, 41 insertions, 30 deletions
@@ -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"); } @@ -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 */ @@ -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; |