diff --git a/core/object/object.cpp b/core/object/object.cpp index c324eab9bbd2..39cae7c5bd1d 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -195,14 +195,15 @@ bool Object::_predelete() { _predelete_ok = 1; notification(NOTIFICATION_PREDELETE, true); if (_predelete_ok) { - _class_ptr = nullptr; //must restore so destructors can access class ptr correctly + _class_name_ptr = nullptr; // Must restore, so constructors/destructors have proper class name access at each stage. } return _predelete_ok; } void Object::_postinitialize() { - _class_ptr = _get_class_namev(); + _class_name_ptr = _get_class_namev(); // Set the direct pointer, which is much faster to obtain, but can only happen after postinitialize. _initialize_classv(); + _class_name_ptr = nullptr; // May have been called from a constructor. notification(NOTIFICATION_POSTINITIALIZE); } diff --git a/core/object/object.h b/core/object/object.h index 5ec69a371b0b..4226b5e67b9e 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -376,7 +376,6 @@ public: \ #define GDCLASS(m_class, m_inherits) \ private: \ void operator=(const m_class &p_rval) {} \ - mutable StringName _class_name; \ friend class ::ClassDB; \ \ public: \ @@ -388,13 +387,11 @@ public: return String(#m_class); \ } \ virtual const StringName *_get_class_namev() const override { \ - if (_get_extension()) { \ - return &_get_extension()->class_name; \ - } \ - if (!_class_name) { \ - _class_name = get_class_static(); \ + static StringName _class_name_static; \ + if (unlikely(!_class_name_static)) { \ + StringName::assign_static_unique_class_name(&_class_name_static, #m_class); \ } \ - return &_class_name; \ + return &_class_name_static; \ } \ static _FORCE_INLINE_ void *get_class_ptr_static() { \ static int ptr; \ @@ -614,8 +611,7 @@ class Object { Variant script; // Reference does not exist yet, store it in a Variant. HashMap metadata; HashMap metadata_properties; - mutable StringName _class_name; - mutable const StringName *_class_ptr = nullptr; + mutable const StringName *_class_name_ptr = nullptr; void _add_user_signal(const String &p_name, const Array &p_args = Array()); bool _has_user_signal(const StringName &p_name) const; @@ -714,10 +710,11 @@ class Object { Variant _call_deferred_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); virtual const StringName *_get_class_namev() const { - if (!_class_name) { - _class_name = get_class_static(); + static StringName _class_name_static; + if (unlikely(!_class_name_static)) { + StringName::assign_static_unique_class_name(&_class_name_static, "Object"); } - return &_class_name; + return &_class_name_static; } Vector _get_meta_list_bind() const; @@ -788,13 +785,16 @@ class Object { _FORCE_INLINE_ const StringName &get_class_name() const { if (_extension) { + // Can't put inside the unlikely as constructor can run it return _extension->class_name; } - if (!_class_ptr) { + + if (unlikely(!_class_name_ptr)) { + // While class is initializing / deinitializing, constructors and destructurs + // need access to the proper class at the proper stage. return *_get_class_namev(); - } else { - return *_class_ptr; } + return *_class_name_ptr; } /* IAPI */ diff --git a/core/string/string_name.cpp b/core/string/string_name.cpp index df9b6b3f1aad..6099fea13f5d 100644 --- a/core/string/string_name.cpp +++ b/core/string/string_name.cpp @@ -201,6 +201,14 @@ StringName::StringName(const StringName &p_name) { } } +void StringName::assign_static_unique_class_name(StringName *ptr, const char *p_name) { + mutex.lock(); + if (*ptr == StringName()) { + *ptr = StringName(p_name, true); + } + mutex.unlock(); +} + StringName::StringName(const char *p_name, bool p_static) { _data = nullptr; diff --git a/core/string/string_name.h b/core/string/string_name.h index 177e82896d33..07abc781a287 100644 --- a/core/string/string_name.h +++ b/core/string/string_name.h @@ -177,6 +177,8 @@ class StringName { StringName(const String &p_name, bool p_static = false); StringName(const StaticCString &p_static_string, bool p_static = false); StringName() {} + + static void assign_static_unique_class_name(StringName *ptr, const char *p_name); _FORCE_INLINE_ ~StringName() { if (likely(configured) && _data) { //only free if configured unref();