diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2021-12-07 11:26:18 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-07 19:26:18 +0000 |
commit | 756f90b4bb91e842ca8c49f30062c4b7af97010d (patch) | |
tree | fbe36399e8a402128dc31fbe8765cd15939e7da5 /src | |
parent | d0688359cacd50ce11858f8a22411ebce87d872d (diff) | |
download | binaryen-756f90b4bb91e842ca8c49f30062c4b7af97010d.tar.gz binaryen-756f90b4bb91e842ca8c49f30062c4b7af97010d.tar.bz2 binaryen-756f90b4bb91e842ca8c49f30062c4b7af97010d.zip |
[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<TypeInfo>` or `std::unique_ptr<HeapTypeInfo>`. Previously these
two code paths had separate, similar logic. To reduce deduplication, combine
both code paths into a single method.
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm/wasm-type.cpp | 101 |
1 files changed, 51 insertions, 50 deletions
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<typename Info> struct Store { bool isGlobalStore(); #endif - typename Info::type_t insert(const Info& info); - typename Info::type_t insert(std::unique_ptr<Info>&& info); + typename Info::type_t insert(const Info& info) { return doInsert(info); } + typename Info::type_t insert(std::unique_ptr<Info>&& info) { + return doInsert(info); + } bool hasCanonical(const Info& info, typename Info::type_t& canonical); private: - TypeID doInsert(std::unique_ptr<Info>&& info); + template<typename Ref> typename Info::type_t doInsert(Ref& infoRef) { + const Info& info = [&]() { + if constexpr (std::is_same_v<Ref, const Info>) { + return infoRef; + } else if constexpr (std::is_same_v<Ref, std::unique_ptr<Info>>) { + infoRef->isTemp = false; + return *infoRef; + } + }(); + + auto getPtr = [&]() -> std::unique_ptr<Info> { + if constexpr (std::is_same_v<Ref, const Info>) { + return std::make_unique<Info>(infoRef); + } else if constexpr (std::is_same_v<Ref, std::unique_ptr<Info>>) { + 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<std::recursive_mutex> lock(mutex); + // Nominal HeapTypes are always unique, so don't bother deduplicating them. + if constexpr (std::is_same_v<Info, HeapTypeInfo>) { + 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<TypeInfo>; @@ -709,43 +757,6 @@ template<typename Info> bool Store<Info>::isGlobalStore() { #endif template<typename Info> -typename Info::type_t Store<Info>::insert(const Info& info) { - if (auto canon = info.getCanonical()) { - return *canon; - } - std::lock_guard<std::recursive_mutex> lock(mutex); - // Only HeapTypes in Nominal mode should be unconditionally added. In all - // other cases, deduplicate with existing types. - if (std::is_same<Info, TypeInfo>::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>(info))); -} - -template<typename Info> -typename Info::type_t Store<Info>::insert(std::unique_ptr<Info>&& info) { - if (auto canon = info->getCanonical()) { - return *canon; - } - std::lock_guard<std::recursive_mutex> lock(mutex); - // Only HeapTypes in Nominal mode should be unconditionally added. In all - // other cases, deduplicate with existing types. - if (std::is_same<Info, TypeInfo>::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<typename Info> bool Store<Info>::hasCanonical(const Info& info, typename Info::type_t& out) { auto indexIt = typeIDs.find(std::cref(info)); if (indexIt != typeIDs.end()) { @@ -755,16 +766,6 @@ bool Store<Info>::hasCanonical(const Info& info, typename Info::type_t& out) { return false; } -template<typename Info> -TypeID Store<Info>::doInsert(std::unique_ptr<Info>&& 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<Type> types) : Type(Tuple(types)) {} |