Merge pull request #111337 from Ivorforce/gdvirtual-init-virtual-ptr

Abstract `Object` virtual pointer init into a method instead of duplicating it across `gdvirtual.gen.inc`
This commit is contained in:
Thaddeus Crews 2025-10-07 11:54:31 -05:00
commit 1c643549f3
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
3 changed files with 33 additions and 51 deletions

View file

@ -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<void*>(_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<void*>(_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<void*>(_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<void*>(_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<uintptr_t>(-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):

View file

@ -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<void *>(_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

View file

@ -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; }