From c7e8a998ffcb30b328ec12a776f80e4ad11a0c90 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Tue, 27 Aug 2024 12:23:10 +0200 Subject: [PATCH] meta: reduce cost of meta func --- src/entt/meta/factory.hpp | 39 ++++++++++++++++----------------------- src/entt/meta/meta.hpp | 12 ++++++++---- src/entt/meta/node.hpp | 19 +------------------ 3 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/entt/meta/factory.hpp b/src/entt/meta/factory.hpp index dafafb4fb..31dd469f0 100644 --- a/src/entt/meta/factory.hpp +++ b/src/entt/meta/factory.hpp @@ -38,13 +38,15 @@ class basic_meta_factory { } static auto *find_overload(meta_func_node *curr, invoke_type *const ref) { - for(; curr->invoke != ref; curr = curr->next.get()) {} - ENTT_ASSERT(curr != nullptr, "Cannot find overload"); + while(curr && (curr->invoke != ref)) { + curr = curr->next.get(); + } + return curr; } - void reset_bucket(const id_type id) { - invoke = nullptr; + void reset_bucket(const id_type id, invoke_type *const ref = nullptr) { + invoke = ref; bucket = id; } @@ -90,25 +92,16 @@ class basic_meta_factory { } void func(meta_func_node node) { - reset_bucket(node.id); + reset_bucket(node.id, node.invoke); - if(auto it = details->func.find(node.id); it == details->func.end()) { - auto &&elem = details->func.insert_or_assign(node.id, std::move(node)).first; - invoke = elem->second.invoke; - } else { - auto *curr = &it->second; - - while(curr->invoke != node.invoke && curr->next) { - curr = curr->next.get(); + if(auto *member = find_member(details->func, node.id); member == nullptr) { + details->func.emplace_back(std::move(node)); + } else if(auto *overload = find_overload(member, node.invoke); overload == nullptr) { + while(member->next != nullptr) { + member = member->next.get(); } - if(curr->invoke == node.invoke) { - invoke = curr->invoke; - } else { - invoke = node.invoke; - curr->next = std::make_shared(); - *curr->next = std::move(node); - } + member->next = std::make_shared(std::move(node)); } } @@ -120,7 +113,7 @@ class basic_meta_factory { } else if(invoke == nullptr) { container = &find_member(details->data, bucket)->prop; } else { - container = &find_overload(&details->func[bucket], invoke)->prop; // wait until func is a vector too: find_member(details->func, bucket); + container = &find_overload(find_member(details->func, bucket), invoke)->prop; } std::size_t pos{}; @@ -134,7 +127,7 @@ class basic_meta_factory { } else if(invoke == nullptr) { find_member(details->data, bucket)->traits |= value; } else { - find_overload(&details->func[bucket], invoke)->traits |= value; // wait until func is a vector too: find_member(details->func, bucket); + find_overload(find_member(details->func, bucket), invoke)->traits |= value; } } @@ -144,7 +137,7 @@ class basic_meta_factory { } else if(invoke == nullptr) { find_member(details->data, bucket)->custom = std::move(node); } else { - find_overload(&details->func[bucket], invoke)->custom = std::move(node); // wait until func is a vector too: find_member(details->func, bucket); + find_overload(find_member(details->func, bucket), invoke)->custom = std::move(node); } } diff --git a/src/entt/meta/meta.hpp b/src/entt/meta/meta.hpp index 9ec77131a..6f1ffbdb0 100644 --- a/src/entt/meta/meta.hpp +++ b/src/entt/meta/meta.hpp @@ -1454,7 +1454,7 @@ class meta_type { * @return The registered meta function for the given identifier, if any. */ [[nodiscard]] meta_func func(const id_type id) const { - const auto *elem = internal::deprecated_look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id); + const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id); return elem ? meta_func{*ctx, *elem} : meta_func{}; } @@ -1514,9 +1514,13 @@ class meta_type { */ meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const { if(node.details) { - if(auto it = node.details->func.find(id); it != node.details->func.cend()) { - if(const auto *candidate = lookup(args, sz, instance && (instance->data() == nullptr), [curr = &it->second]() mutable { return curr ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) { - return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args); + for(auto &&elem: node.details->func) { + if(elem.id == id) { + if(const auto *candidate = lookup(args, sz, instance && (instance->data() == nullptr), [curr = &elem]() mutable { return curr ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) { + return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args); + } + + break; } } } diff --git a/src/entt/meta/node.hpp b/src/entt/meta/node.hpp index 883863bb0..1da2fede8 100644 --- a/src/entt/meta/node.hpp +++ b/src/entt/meta/node.hpp @@ -139,7 +139,7 @@ struct meta_type_descriptor { dense_map base{}; std::vector conv{}; std::vector data{}; - dense_map func{}; + std::vector func{}; std::vector prop{}; }; @@ -161,23 +161,6 @@ struct meta_type_node { std::shared_ptr details{}; }; -template -auto *deprecated_look_for(const meta_context &context, const meta_type_node &node, const id_type id) { - if(node.details) { - if(const auto it = (node.details.get()->*Member).find(id); it != (node.details.get()->*Member).cend()) { - return &it->second; - } - - for(auto &&curr: node.details->base) { - if(auto *elem = deprecated_look_for(context, curr.second.type(context), id); elem) { - return elem; - } - } - } - - return static_cast*Member)>::mapped_type *>(nullptr); -} - template auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id) { if(node.details) {