summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/wasm/wasm-type.cpp101
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)) {}