Procházet zdrojové kódy

meta: reduce cost of meta func

Michele Caini před 1 rokem
rodič
revize
c7e8a998ff
3 změnil soubory, kde provedl 25 přidání a 45 odebrání
  1. 16 23
      src/entt/meta/factory.hpp
  2. 8 4
      src/entt/meta/meta.hpp
  3. 1 18
      src/entt/meta/node.hpp

+ 16 - 23
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 @@ protected:
     }
 
     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<meta_func_node>();
-                *curr->next = std::move(node);
-            }
+            member->next = std::make_shared<meta_func_node>(std::move(node));
         }
     }
 
@@ -120,7 +113,7 @@ protected:
         } 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 @@ protected:
         } 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 @@ protected:
         } 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);
         }
     }
 

+ 8 - 4
src/entt/meta/meta.hpp

@@ -1454,7 +1454,7 @@ public:
      * @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 @@ public:
      */
     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;
                 }
             }
         }

+ 1 - 18
src/entt/meta/node.hpp

@@ -139,7 +139,7 @@ struct meta_type_descriptor {
     dense_map<id_type, meta_base_node, identity> base{};
     std::vector<meta_conv_node> conv{};
     std::vector<meta_data_node> data{};
-    dense_map<id_type, meta_func_node, identity> func{};
+    std::vector<meta_func_node> func{};
     std::vector<meta_prop_node> prop{};
 };
 
@@ -161,23 +161,6 @@ struct meta_type_node {
     std::shared_ptr<meta_type_descriptor> details{};
 };
 
-template<auto Member>
-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<Member>(context, curr.second.type(context), id); elem) {
-                return elem;
-            }
-        }
-    }
-
-    return static_cast<typename std::remove_reference_t<decltype(node.details.get()->*Member)>::mapped_type *>(nullptr);
-}
-
 template<auto Member>
 auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id) {
     if(node.details) {