From 184448a7b829ad19ad3c239e9e0ddab0a56fc2fe Mon Sep 17 00:00:00 2001 From: alandefreitas Date: Tue, 19 Nov 2024 13:03:17 -0300 Subject: [PATCH] perf(OverlayObjectImpl): fold empty overlays --- src/lib/Support/Handlebars.cpp | 108 +++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 6 deletions(-) diff --git a/src/lib/Support/Handlebars.cpp b/src/lib/Support/Handlebars.cpp index 33b8294f9..6542bfd35 100644 --- a/src/lib/Support/Handlebars.cpp +++ b/src/lib/Support/Handlebars.cpp @@ -89,6 +89,7 @@ isEmpty(dom::Value const& arg) class OverlayObjectImpl : public dom::ObjectImpl { + std::vector grandParents_; dom::Object parent_; dom::Object child_; @@ -96,13 +97,47 @@ class OverlayObjectImpl : public dom::ObjectImpl ~OverlayObjectImpl() override = default; OverlayObjectImpl(dom::Object parent) - : parent_(std::move(parent)) - {} + { + auto* parImpl = parent.impl().get(); + auto* parOverlay = dynamic_cast(parImpl); + if (parOverlay == nullptr) + { + parent_ = std::move(parent); + } + else if (parOverlay->child_.empty()) + { + grandParents_ = parOverlay->grandParents_; + parent_ = parOverlay->parent_; + } + else + { + grandParents_.push_back(parOverlay->parent_); + grandParents_.insert( + grandParents_.end(), + parOverlay->grandParents_.begin(), + parOverlay->grandParents_.end()); + parent_ = parOverlay->child_; + } + } OverlayObjectImpl(dom::Object child, dom::Object parent) - : parent_(std::move(parent)) - , child_(std::move(child)) - {} + : OverlayObjectImpl(std::move(parent)) + { + child_ = std::move(child); + auto* childOverlay = dynamic_cast(child_.impl().get()); + if (childOverlay != nullptr) + { + grandParents_.insert( + grandParents_.begin(), + parent_); + grandParents_.insert( + grandParents_.end(), + childOverlay->grandParents_.begin(), + childOverlay->grandParents_.end()); + parent_ = childOverlay->parent_; + child_ = childOverlay->child_; + } + } std::size_t size() const override { @@ -113,6 +148,17 @@ class OverlayObjectImpl : public dom::ObjectImpl { --n; } + else + { + for (auto const& grandParent : grandParents_) + { + if (grandParent.exists(key)) + { + --n; + break; + } + } + } }); return n; }; @@ -127,6 +173,13 @@ class OverlayObjectImpl : public dom::ObjectImpl { return parent_.get(key); } + for (auto const& grandParent : grandParents_) + { + if (grandParent.exists(key)) + { + return grandParent.get(key); + } + } return dom::Kind::Undefined; } @@ -154,12 +207,55 @@ class OverlayObjectImpl : public dom::ObjectImpl { return false; } + + for (std::size_t i = 0; i < grandParents_.size(); ++i) + { + auto visit_if_not_in_prev = [&]( + dom::String const& key, dom::Value const& value) + { + if (child_.exists(key)) + { + return true; + } + if (parent_.exists(key)) + { + return true; + } + for (std::size_t j = 0; j < i; ++j) + { + if (grandParents_[j].exists(key)) + { + return true; + } + } + return fn(key, value); + }; + if (!grandParents_[i].visit(visit_if_not_in_prev)) + { + return false; + } + } return true; } bool exists(std::string_view key) const override { - return child_.exists(key) || parent_.exists(key); + if (child_.exists(key)) + { + return true; + } + if (parent_.exists(key)) + { + return true; + } + for (auto const& grandParent : grandParents_) + { + if (grandParent.exists(key)) + { + return true; + } + } + return false; } };