diff options
Diffstat (limited to 'core/object')
-rw-r--r-- | core/object/callable_method_pointer.cpp | 22 | ||||
-rw-r--r-- | core/object/class_db.cpp | 4 | ||||
-rw-r--r-- | core/object/class_db.h | 4 | ||||
-rw-r--r-- | core/object/message_queue.cpp | 51 | ||||
-rw-r--r-- | core/object/object.h | 10 | ||||
-rw-r--r-- | core/object/script_language.h | 1 |
6 files changed, 53 insertions, 39 deletions
diff --git a/core/object/callable_method_pointer.cpp b/core/object/callable_method_pointer.cpp index b53985e6b7..ed400788b1 100644 --- a/core/object/callable_method_pointer.cpp +++ b/core/object/callable_method_pointer.cpp @@ -38,13 +38,10 @@ bool CallableCustomMethodPointerBase::compare_equal(const CallableCustom *p_a, c return false; } - for (uint32_t i = 0; i < a->comp_size; i++) { - if (a->comp_ptr[i] != b->comp_ptr[i]) { - return false; - } - } - - return true; + // Avoid sorting by memory address proximity, which leads to unpredictable performance over time + // due to the reuse of old addresses for newer objects. Use byte-wise comparison to leverage the + // backwards encoding of little-endian systems as a way to decouple spatiality and time. + return memcmp(a->comp_ptr, b->comp_ptr, a->comp_size * 4) == 0; } bool CallableCustomMethodPointerBase::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) { @@ -55,15 +52,8 @@ bool CallableCustomMethodPointerBase::compare_less(const CallableCustom *p_a, co return a->comp_size < b->comp_size; } - for (uint32_t i = 0; i < a->comp_size; i++) { - if (a->comp_ptr[i] == b->comp_ptr[i]) { - continue; - } - - return a->comp_ptr[i] < b->comp_ptr[i]; - } - - return false; + // See note in compare_equal(). + return memcmp(a->comp_ptr, b->comp_ptr, a->comp_size * 4) < 0; } CallableCustom::CompareEqualFunc CallableCustomMethodPointerBase::get_compare_equal_func() const { diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index cc4a29164d..c8c50fb957 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -53,7 +53,7 @@ MethodDefinition D_METHODP(const char *p_name, const char *const **p_args, uint3 #endif ClassDB::APIType ClassDB::current_api = API_CORE; -HashMap<ClassDB::APIType, uint64_t> ClassDB::api_hashes_cache; +HashMap<ClassDB::APIType, uint32_t> ClassDB::api_hashes_cache; void ClassDB::set_current_api(APIType p_api) { DEV_ASSERT(!api_hashes_cache.has(p_api)); // This API type may not be suitable for caching of hash if it can change later. @@ -163,7 +163,7 @@ ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) { return ti->api; } -uint64_t ClassDB::get_api_hash(APIType p_api) { +uint32_t ClassDB::get_api_hash(APIType p_api) { OBJTYPE_RLOCK; #ifdef DEBUG_METHODS_ENABLED diff --git a/core/object/class_db.h b/core/object/class_db.h index ce64336a45..3aae3b452e 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -155,7 +155,7 @@ public: #endif static APIType current_api; - static HashMap<APIType, uint64_t> api_hashes_cache; + static HashMap<APIType, uint32_t> api_hashes_cache; static void _add_class2(const StringName &p_class, const StringName &p_inherits); @@ -246,7 +246,7 @@ public: static APIType get_api_type(const StringName &p_class); - static uint64_t get_api_hash(APIType p_api); + static uint32_t get_api_hash(APIType p_api); template <typename> struct member_function_traits; diff --git a/core/object/message_queue.cpp b/core/object/message_queue.cpp index 506f8291eb..dd7aba1384 100644 --- a/core/object/message_queue.cpp +++ b/core/object/message_queue.cpp @@ -35,6 +35,10 @@ #include "core/object/class_db.h" #include "core/object/script_language.h" +#ifdef DEBUG_ENABLED +#include "core/config/engine.h" +#endif + #ifdef DEV_ENABLED // Includes sanity checks to ensure that a queue set as a thread singleton override // is only ever called from the thread it was set for. @@ -316,25 +320,34 @@ Error CallQueue::flush() { Object *target = message->callable.get_object(); UNLOCK_MUTEX; - - switch (message->type & FLAG_MASK) { - case TYPE_CALL: { - if (target || (message->type & FLAG_NULL_IS_OK)) { - Variant *args = (Variant *)(message + 1); - _call_function(message->callable, args, message->args, message->type & FLAG_SHOW_ERROR); - } - } break; - case TYPE_NOTIFICATION: { - if (target) { - target->notification(message->notification); - } - } break; - case TYPE_SET: { - if (target) { - Variant *arg = (Variant *)(message + 1); - target->set(message->callable.get_method(), *arg); - } - } break; +#ifdef DEBUG_ENABLED + if (!message->callable.is_valid()) { + // The editor would cause many of these. + if (!Engine::get_singleton()->is_editor_hint()) { + ERR_PRINT("Trying to execute a deferred call/notification/set on a previously freed instance. Consider using queue_free() instead of free()."); + } + } else +#endif + { + switch (message->type & FLAG_MASK) { + case TYPE_CALL: { + if (target || (message->type & FLAG_NULL_IS_OK)) { + Variant *args = (Variant *)(message + 1); + _call_function(message->callable, args, message->args, message->type & FLAG_SHOW_ERROR); + } + } break; + case TYPE_NOTIFICATION: { + if (target) { + target->notification(message->notification); + } + } break; + case TYPE_SET: { + if (target) { + Variant *arg = (Variant *)(message + 1); + target->set(message->callable.get_method(), *arg); + } + } break; + } } if ((message->type & FLAG_MASK) != TYPE_NOTIFICATION) { diff --git a/core/object/object.h b/core/object/object.h index a3e9d025ea..318dbf98de 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -430,6 +430,9 @@ protected: _FORCE_INLINE_ static void (*_get_bind_methods())() { \ return &m_class::_bind_methods; \ } \ + _FORCE_INLINE_ static void (*_get_bind_compatibility_methods())() { \ + return &m_class::_bind_compatibility_methods; \ + } \ \ public: \ static void initialize_class() { \ @@ -442,6 +445,9 @@ public: if (m_class::_get_bind_methods() != m_inherits::_get_bind_methods()) { \ _bind_methods(); \ } \ + if (m_class::_get_bind_compatibility_methods() != m_inherits::_get_bind_compatibility_methods()) { \ + _bind_compatibility_methods(); \ + } \ initialized = true; \ } \ \ @@ -674,6 +680,7 @@ protected: virtual void _notificationv(int p_notification, bool p_reversed) {} static void _bind_methods(); + static void _bind_compatibility_methods() {} bool _set(const StringName &p_name, const Variant &p_property) { return false; }; bool _get(const StringName &p_name, Variant &r_property) const { return false; }; void _get_property_list(List<PropertyInfo> *p_list) const {}; @@ -685,6 +692,9 @@ protected: _FORCE_INLINE_ static void (*_get_bind_methods())() { return &Object::_bind_methods; } + _FORCE_INLINE_ static void (*_get_bind_compatibility_methods())() { + return &Object::_bind_compatibility_methods; + } _FORCE_INLINE_ bool (Object::*_get_get() const)(const StringName &p_name, Variant &r_ret) const { return &Object::_get; } diff --git a/core/object/script_language.h b/core/object/script_language.h index 2b685c77a3..3ea6a6e4c3 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -263,6 +263,7 @@ public: }; struct ScriptError { + String path; int line = -1; int column = -1; String message; |