From e9b3eee6d35083b0fcbef055e19da8abd90f09c1 Mon Sep 17 00:00:00 2001 From: skypjack Date: Mon, 15 Sep 2025 14:45:31 +0200 Subject: [PATCH] meta: static local meta type node fallback --- src/entt/meta/factory.hpp | 52 ++++++++++++++++++++++----------------- src/entt/meta/meta.hpp | 12 ++++----- src/entt/meta/node.hpp | 27 ++++++++++---------- 3 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/entt/meta/factory.hpp b/src/entt/meta/factory.hpp index 1a217f773..6be4ada30 100644 --- a/src/entt/meta/factory.hpp +++ b/src/entt/meta/factory.hpp @@ -32,14 +32,18 @@ namespace internal { class basic_meta_factory { using invoke_type = std::remove_pointer_t; + auto &fetch_node() noexcept { + return meta_context::from(*ctx).value[parent]; + } + auto *find_member_or_assert() { - auto *member = find_member<&meta_data_node::id>(details->data, bucket); + auto *member = find_member<&meta_data_node::id>(fetch_node().details->data, bucket); ENTT_ASSERT(member != nullptr, "Cannot find member"); return member; } auto *find_overload_or_assert() { - auto *overload = find_overload(find_member<&meta_func_node::id>(details->func, bucket), invoke); + auto *overload = find_overload(find_member<&meta_func_node::id>(fetch_node().details->func, bucket), invoke); ENTT_ASSERT(overload != nullptr, "Cannot find overload"); return overload; } @@ -52,7 +56,7 @@ class basic_meta_factory { protected: void type(const id_type id, const char *name) noexcept { reset_bucket(parent); - auto &&elem = meta_context::from(*ctx).value[parent]; + auto &elem = fetch_node(); ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier"); elem.name = name; elem.id = id; @@ -60,36 +64,42 @@ protected: template void insert_or_assign(Type node) { + auto &elem = fetch_node(); + reset_bucket(parent); if constexpr(std::is_same_v) { - auto *member = find_member<&meta_base_node::type>(details->base, node.type); - member ? (*member = node) : details->base.emplace_back(node); + auto *member = find_member<&meta_base_node::type>(elem.details->base, node.type); + member ? (*member = node) : elem.details->base.emplace_back(node); } else if constexpr(std::is_same_v) { - auto *member = find_member<&meta_conv_node::type>(details->conv, node.type); - member ? (*member = node) : details->conv.emplace_back(node); + auto *member = find_member<&meta_conv_node::type>(elem.details->conv, node.type); + member ? (*member = node) : elem.details->conv.emplace_back(node); } else { static_assert(std::is_same_v, "Unexpected type"); - auto *member = find_member<&meta_ctor_node::id>(details->ctor, node.id); - member ? (*member = node) : details->ctor.emplace_back(node); + auto *member = find_member<&meta_ctor_node::id>(elem.details->ctor, node.id); + member ? (*member = node) : elem.details->ctor.emplace_back(node); } } void data(meta_data_node node) { + auto &elem = fetch_node(); + reset_bucket(node.id); - if(auto *member = find_member<&meta_data_node::id>(details->data, node.id); member == nullptr) { - details->data.emplace_back(std::move(node)); + if(auto *member = find_member<&meta_data_node::id>(elem.details->data, node.id); member == nullptr) { + elem.details->data.emplace_back(std::move(node)); } else if(member->set != node.set || member->get != node.get) { *member = std::move(node); } } void func(meta_func_node node) { + auto &elem = fetch_node(); + reset_bucket(node.id, node.invoke); - if(auto *member = find_member<&meta_func_node::id>(details->func, node.id); member == nullptr) { - details->func.emplace_back(std::move(node)); + if(auto *member = find_member<&meta_func_node::id>(elem.details->func, node.id); member == nullptr) { + elem.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(); } member->next = std::make_unique(std::move(node)); @@ -98,7 +108,7 @@ protected: void traits(const meta_traits value) { if(bucket == parent) { - meta_context::from(*ctx).value[bucket].traits |= value; + fetch_node().traits |= value; } else if(invoke == nullptr) { find_member_or_assert()->traits |= value; } else { @@ -108,7 +118,7 @@ protected: void custom(meta_custom_node node) { if(bucket == parent) { - details->custom = std::move(node); + fetch_node().details->custom = std::move(node); } else if(invoke == nullptr) { find_member_or_assert()->custom = std::move(node); } else { @@ -117,15 +127,12 @@ protected: } public: - basic_meta_factory(meta_ctx &area, meta_type_node node) + basic_meta_factory(meta_ctx &area, const meta_type_node &node) : ctx{&area}, parent{node.info->hash()}, - bucket{parent}, - details{node.details.get()} { - if(details == nullptr) { - node.details = std::make_shared(); - meta_context::from(*ctx).value[parent] = node; - details = node.details.get(); + bucket{parent} { + if(auto &curr = meta_context::from(*ctx).value.try_emplace(parent, node).first->second; curr.details == nullptr) { + curr.details = std::make_shared(); } } @@ -134,7 +141,6 @@ private: id_type parent{}; id_type bucket{}; invoke_type *invoke{}; - meta_type_descriptor *details{}; }; } // namespace internal diff --git a/src/entt/meta/meta.hpp b/src/entt/meta/meta.hpp index 273a6f5c9..24a10e51f 100644 --- a/src/entt/meta/meta.hpp +++ b/src/entt/meta/meta.hpp @@ -76,8 +76,8 @@ public: private: const meta_ctx *ctx{}; const void *data{}; - internal::meta_type_node (*value_type_node)(const internal::meta_context &){}; - internal::meta_type_node (*const_reference_node)(const internal::meta_context &){}; + const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){}; + const internal::meta_type_node &(*const_reference_node)(const internal::meta_context &){}; size_type (*size_fn)(const void *){}; bool (*clear_fn)(void *){}; bool (*reserve_fn)(void *, const size_type){}; @@ -142,9 +142,9 @@ public: private: const meta_ctx *ctx{}; const void *data{}; - internal::meta_type_node (*key_type_node)(const internal::meta_context &){}; - internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){}; - internal::meta_type_node (*value_type_node)(const internal::meta_context &){}; + const internal::meta_type_node &(*key_type_node)(const internal::meta_context &){}; + const internal::meta_type_node &(*mapped_type_node)(const internal::meta_context &){}; + const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){}; size_type (*size_fn)(const void *){}; bool (*clear_fn)(void *){}; bool (*reserve_fn)(void *, const size_type){}; @@ -629,7 +629,7 @@ public: private: any storage; const meta_ctx *ctx{&locator::value_or()}; - internal::meta_type_node (*resolve)(const internal::meta_context &) noexcept {}; + const internal::meta_type_node &(*resolve)(const internal::meta_context &) noexcept {}; mutable internal::meta_type_node lazy_node{}; vtable_type *vtable{}; }; diff --git a/src/entt/meta/node.hpp b/src/entt/meta/node.hpp index 8fb9330e6..5b1d5b989 100644 --- a/src/entt/meta/node.hpp +++ b/src/entt/meta/node.hpp @@ -69,7 +69,7 @@ struct meta_custom_node { struct meta_base_node { id_type type{}; - meta_type_node (*resolve)(const meta_context &) noexcept {}; + const meta_type_node &(*resolve)(const meta_context &) noexcept {}; const void *(*cast)(const void *) noexcept {}; }; @@ -94,7 +94,7 @@ struct meta_data_node { const char *name{}; meta_traits traits{meta_traits::is_none}; size_type arity{0u}; - meta_type_node (*type)(const meta_context &) noexcept {}; + const meta_type_node &(*type)(const meta_context &) noexcept {}; meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; bool (*set)(meta_handle, meta_any){}; meta_any (*get)(meta_handle){}; @@ -108,7 +108,7 @@ struct meta_func_node { const char *name{}; meta_traits traits{meta_traits::is_none}; size_type arity{0u}; - meta_type_node (*ret)(const meta_context &) noexcept {}; + const meta_type_node &(*ret)(const meta_context &) noexcept {}; meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; meta_any (*invoke)(meta_handle, meta_any *const){}; std::unique_ptr next; @@ -119,8 +119,8 @@ struct meta_template_node { using size_type = std::size_t; size_type arity{0u}; - meta_type_node (*resolve)(const meta_context &) noexcept {}; - meta_type_node (*arg)(const meta_context &, const size_type) noexcept {}; + const meta_type_node &(*resolve)(const meta_context &) noexcept {}; + const meta_type_node &(*arg)(const meta_context &, const size_type) noexcept {}; }; struct meta_type_descriptor { @@ -140,7 +140,7 @@ struct meta_type_node { const char *name{}; meta_traits traits{meta_traits::is_none}; size_type size_of{0u}; - meta_type_node (*remove_pointer)(const meta_context &) noexcept {}; + const meta_type_node &(*remove_pointer)(const meta_context &) noexcept {}; meta_any (*default_constructor)(const meta_ctx &){}; double (*conversion_helper)(void *, const void *){}; meta_any (*from_void)(const meta_ctx &, void *, const void *){}; @@ -184,11 +184,11 @@ template } template -meta_type_node resolve(const meta_context &) noexcept; +const meta_type_node &resolve(const meta_context &) noexcept; template -[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list, [[maybe_unused]] const std::size_t index) noexcept { - meta_type_node (*value)(const meta_context &) noexcept = nullptr; +[[nodiscard]] const meta_type_node &meta_arg_node(const meta_context &context, type_list, [[maybe_unused]] const std::size_t index) noexcept { + const meta_type_node &(*value)(const meta_context &) noexcept = nullptr; if constexpr(sizeof...(Args) != 0u) { std::size_t pos{}; @@ -294,7 +294,7 @@ auto setup_node_for() noexcept { node.templ = meta_template_node{ meta_template_traits::args_type::size, &resolve::class_type>, - +[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits::args_type{}, index); }}; + +[](const meta_context &area, const std::size_t index) noexcept -> decltype(auto) { return meta_arg_node(area, typename meta_template_traits::args_type{}, index); }}; } return node; @@ -306,10 +306,11 @@ auto setup_node_for() noexcept { } template -[[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept { +[[nodiscard]] const meta_type_node &resolve(const meta_context &context) noexcept { static_assert(std::is_same_v>>, "Invalid type"); - const auto *elem = try_resolve(context, type_id()); - return (elem == nullptr) ? setup_node_for() : *elem; + static const meta_type_node node = setup_node_for(); + const auto *elem = try_resolve(context, *node.info); + return (elem == nullptr) ? node : *elem; } } // namespace internal