Skip to content

Commit

Permalink
meta: reduce cost of meta func
Browse files Browse the repository at this point in the history
  • Loading branch information
skypjack committed Aug 27, 2024
1 parent a4ad1ac commit c7e8a99
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 45 deletions.
39 changes: 16 additions & 23 deletions src/entt/meta/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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<meta_func_node>();
*curr->next = std::move(node);
}
member->next = std::make_shared<meta_func_node>(std::move(node));
}
}

Expand All @@ -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{};
Expand All @@ -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;
}
}

Expand All @@ -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);
}
}

Expand Down
12 changes: 8 additions & 4 deletions src/entt/meta/meta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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{};
}

Expand Down Expand Up @@ -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;
}
}
}
Expand Down
19 changes: 1 addition & 18 deletions src/entt/meta/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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{};
};

Expand All @@ -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) {
Expand Down

0 comments on commit c7e8a99

Please sign in to comment.