From 756f90b4bb91e842ca8c49f30062c4b7af97010d Mon Sep 17 00:00:00 2001 From: Thomas Lively <7121787+tlively@users.noreply.github.com> Date: Tue, 7 Dec 2021 11:26:18 -0800 Subject: [NFC] Deduplicate Store insertion logic (#4374) Types and HeapTypes are inserted into their respective stores either by copying a reference to a `TypeInfo` or `HeapTypeInfo` or by moving a `std::unique_ptr` or `std::unique_ptr`. Previously these two code paths had separate, similar logic. To reduce deduplication, combine both code paths into a single method. --- src/wasm/wasm-type.cpp | 101 +++++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 37f24c361..e0b3d0262 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -671,12 +671,60 @@ template struct Store { bool isGlobalStore(); #endif - typename Info::type_t insert(const Info& info); - typename Info::type_t insert(std::unique_ptr&& info); + typename Info::type_t insert(const Info& info) { return doInsert(info); } + typename Info::type_t insert(std::unique_ptr&& info) { + return doInsert(info); + } bool hasCanonical(const Info& info, typename Info::type_t& canonical); private: - TypeID doInsert(std::unique_ptr&& info); + template typename Info::type_t doInsert(Ref& infoRef) { + const Info& info = [&]() { + if constexpr (std::is_same_v) { + return infoRef; + } else if constexpr (std::is_same_v>) { + infoRef->isTemp = false; + return *infoRef; + } + }(); + + auto getPtr = [&]() -> std::unique_ptr { + if constexpr (std::is_same_v) { + return std::make_unique(infoRef); + } else if constexpr (std::is_same_v>) { + return std::move(infoRef); + } + }; + + auto insertNew = [&]() { + assert((!isGlobalStore() || !info.isTemp) && "Leaking temporary type!"); + auto ptr = getPtr(); + TypeID id = uintptr_t(ptr.get()); + assert(id > Info::type_t::_last_basic_type); + typeIDs.insert({*ptr, id}); + constructedTypes.emplace_back(std::move(ptr)); + return typename Info::type_t(id); + }; + + // Turn e.g. (ref null any) into anyref. + if (auto canonical = info.getCanonical()) { + return *canonical; + } + std::lock_guard lock(mutex); + // Nominal HeapTypes are always unique, so don't bother deduplicating them. + if constexpr (std::is_same_v) { + if (info.isNominal || typeSystem == TypeSystem::Nominal) { + return insertNew(); + } + } + // Check whether we already have a type for this structural Info. + auto indexIt = typeIDs.find(std::cref(info)); + if (indexIt != typeIDs.end()) { + return typename Info::type_t(indexIt->second); + } + // We do not have a type for this Info already. Create one. + return insertNew(); + } }; using TypeStore = Store; @@ -708,43 +756,6 @@ template bool Store::isGlobalStore() { } #endif -template -typename Info::type_t Store::insert(const Info& info) { - if (auto canon = info.getCanonical()) { - return *canon; - } - std::lock_guard lock(mutex); - // Only HeapTypes in Nominal mode should be unconditionally added. In all - // other cases, deduplicate with existing types. - if (std::is_same::value || - typeSystem == TypeSystem::Equirecursive) { - auto indexIt = typeIDs.find(std::cref(info)); - if (indexIt != typeIDs.end()) { - return typename Info::type_t(indexIt->second); - } - } - return typename Info::type_t(doInsert(std::make_unique(info))); -} - -template -typename Info::type_t Store::insert(std::unique_ptr&& info) { - if (auto canon = info->getCanonical()) { - return *canon; - } - std::lock_guard lock(mutex); - // Only HeapTypes in Nominal mode should be unconditionally added. In all - // other cases, deduplicate with existing types. - if (std::is_same::value || - typeSystem == TypeSystem::Equirecursive) { - auto indexIt = typeIDs.find(std::cref(*info)); - if (indexIt != typeIDs.end()) { - return typename Info::type_t(indexIt->second); - } - } - info->isTemp = false; - return typename Info::type_t(doInsert(std::move(info))); -} - template bool Store::hasCanonical(const Info& info, typename Info::type_t& out) { auto indexIt = typeIDs.find(std::cref(info)); @@ -755,16 +766,6 @@ bool Store::hasCanonical(const Info& info, typename Info::type_t& out) { return false; } -template -TypeID Store::doInsert(std::unique_ptr&& info) { - assert((!isGlobalStore() || !info->isTemp) && "Leaking temporary type!"); - TypeID id = uintptr_t(info.get()); - assert(id > Info::type_t::_last_basic_type); - typeIDs.insert({*info, id}); - constructedTypes.emplace_back(std::move(info)); - return id; -} - } // anonymous namespace Type::Type(std::initializer_list types) : Type(Tuple(types)) {} -- cgit v1.2.3