diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index e608b984918..9f9662c215e 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -21,19 +21,7 @@ proto = """#define GDVIRTUAL$VER($ALIAS $RET m_name $ARG)\\ $SCRIPTCALL\\ if (_get_extension()) {\\ if (unlikely(!_gdvirtual_##$VARNAME)) {\\ - MethodInfo mi = _gdvirtual_##$VARNAME##_get_method_info();\\ - uint32_t hash = mi.get_compatibility_hash();\\ - _gdvirtual_##$VARNAME = nullptr;\\ - if (_get_extension()->get_virtual_call_data2 && _get_extension()->call_virtual_with_data) {\\ - _gdvirtual_##$VARNAME = _get_extension()->get_virtual_call_data2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\ - } else if (_get_extension()->get_virtual2) {\\ - _gdvirtual_##$VARNAME = (void *)_get_extension()->get_virtual2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\ - }\\ - _GDVIRTUAL_GET_DEPRECATED(_gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT)\\ - _GDVIRTUAL_TRACK(_gdvirtual_##$VARNAME);\\ - if (_gdvirtual_##$VARNAME == nullptr) {\\ - _gdvirtual_##$VARNAME = reinterpret_cast(_INVALID_GDVIRTUAL_FUNC_ADDR);\\ - }\\ + _gdvirtual_init_method_ptr(_gdvirtual_##$VARNAME##_get_method_info().get_compatibility_hash(), _gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT);\\ }\\ if (_gdvirtual_##$VARNAME != reinterpret_cast(_INVALID_GDVIRTUAL_FUNC_ADDR)) {\\ $CALLPTRARGS\\ @@ -57,19 +45,7 @@ proto = """#define GDVIRTUAL$VER($ALIAS $RET m_name $ARG)\\ $SCRIPTHASMETHOD\\ if (_get_extension()) {\\ if (unlikely(!_gdvirtual_##$VARNAME)) {\\ - MethodInfo mi = _gdvirtual_##$VARNAME##_get_method_info();\\ - uint32_t hash = mi.get_compatibility_hash();\\ - _gdvirtual_##$VARNAME = nullptr;\\ - if (_get_extension()->get_virtual_call_data2 && _get_extension()->call_virtual_with_data) {\\ - _gdvirtual_##$VARNAME = _get_extension()->get_virtual_call_data2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\ - } else if (_get_extension()->get_virtual2) {\\ - _gdvirtual_##$VARNAME = (void *)_get_extension()->get_virtual2(_get_extension()->class_userdata, &_gdvirtual_##$VARNAME##_sn, hash);\\ - }\\ - _GDVIRTUAL_GET_DEPRECATED(_gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT)\\ - _GDVIRTUAL_TRACK(_gdvirtual_##$VARNAME);\\ - if (_gdvirtual_##$VARNAME == nullptr) {\\ - _gdvirtual_##$VARNAME = reinterpret_cast(_INVALID_GDVIRTUAL_FUNC_ADDR);\\ - }\\ + _gdvirtual_init_method_ptr(_gdvirtual_##$VARNAME##_get_method_info().get_compatibility_hash(), _gdvirtual_##$VARNAME, _gdvirtual_##$VARNAME##_sn, $COMPAT);\\ }\\ if (_gdvirtual_##$VARNAME != reinterpret_cast(_INVALID_GDVIRTUAL_FUNC_ADDR)) {\\ return true;\\ @@ -221,31 +197,6 @@ def run(target, source, env): inline constexpr uintptr_t _INVALID_GDVIRTUAL_FUNC_ADDR = static_cast(-1); -#ifdef TOOLS_ENABLED -#define _GDVIRTUAL_TRACK(m_virtual)\\ - if (_get_extension()->reloadable) {\\ - VirtualMethodTracker *tracker = memnew(VirtualMethodTracker);\\ - tracker->method = (void **)&m_virtual;\\ - tracker->next = virtual_method_list;\\ - virtual_method_list = tracker;\\ - } -#else -#define _GDVIRTUAL_TRACK(m_virtual) -#endif - -#ifndef DISABLE_DEPRECATED -#define _GDVIRTUAL_GET_DEPRECATED(m_virtual, m_name_sn, m_compat)\\ - else if (m_compat || ClassDB::get_virtual_method_compatibility_hashes(get_class_static(), m_name_sn).size() == 0) {\\ - if (_get_extension()->get_virtual_call_data && _get_extension()->call_virtual_with_data) {\\ - m_virtual = _get_extension()->get_virtual_call_data(_get_extension()->class_userdata, &m_name_sn);\\ - } else if (_get_extension()->get_virtual) {\\ - m_virtual = (void *)_get_extension()->get_virtual(_get_extension()->class_userdata, &m_name_sn);\\ - }\\ - } -#else -#define _GDVIRTUAL_GET_DEPRECATED(m_name, m_name_sn, m_compat) -#endif - """ for i in range(max_versions + 1): diff --git a/core/object/object.cpp b/core/object/object.cpp index 5b9addd83b5..b8d6acd0509 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -959,6 +959,34 @@ Variant Object::call_const(const StringName &p_method, const Variant **p_args, i return ret; } +void Object::_gdvirtual_init_method_ptr(uint32_t p_compat_hash, void *&r_fn_ptr, const StringName &p_fn_name, bool p_compat) const { + r_fn_ptr = nullptr; + if (_extension->get_virtual_call_data2 && _extension->call_virtual_with_data) { + r_fn_ptr = _extension->get_virtual_call_data2(_extension->class_userdata, &p_fn_name, p_compat_hash); + } else if (_extension->get_virtual2) { + r_fn_ptr = (void *)_extension->get_virtual2(_extension->class_userdata, &p_fn_name, p_compat_hash); +#ifndef DISABLE_DEPRECATED + } else if (p_compat || ClassDB::get_virtual_method_compatibility_hashes(get_class_name(), p_fn_name).size() == 0) { + if (_extension->get_virtual_call_data && _extension->call_virtual_with_data) { + r_fn_ptr = _extension->get_virtual_call_data(_extension->class_userdata, &p_fn_name); + } else if (_extension->get_virtual) { + r_fn_ptr = (void *)_extension->get_virtual(_extension->class_userdata, &p_fn_name); + } +#endif + } +#ifdef TOOLS_ENABLED + if (_extension->reloadable) { + VirtualMethodTracker *tracker = memnew(VirtualMethodTracker); + tracker->method = (void **)&r_fn_ptr; + tracker->next = virtual_method_list; + virtual_method_list = tracker; + } +#endif + if (r_fn_ptr == nullptr) { + r_fn_ptr = reinterpret_cast(_INVALID_GDVIRTUAL_FUNC_ADDR); + } +} + void Object::_notification_forward(int p_notification) { // Notify classes starting with Object and ending with most derived subclass. // e.g. Object -> Node -> Node3D diff --git a/core/object/object.h b/core/object/object.h index 4068b0e6b01..2715c7778b5 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -717,6 +717,9 @@ protected: return can_die; } + // Used in gdvirtual.gen.inc + void _gdvirtual_init_method_ptr(uint32_t p_compat_hash, void *&r_fn_ptr, const StringName &p_fn_name, bool p_compat) const; + friend class GDExtensionMethodBind; _ALWAYS_INLINE_ const ObjectGDExtension *_get_extension() const { return _extension; } _ALWAYS_INLINE_ GDExtensionClassInstancePtr _get_extension_instance() const { return _extension_instance; }