summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2020-11-25 12:24:00 -0800
committerGitHub <noreply@github.com>2020-11-25 12:24:00 -0800
commit72c035e905b3695f2763fdeb21163003d8595887 (patch)
tree07b835b752069b441a630111697c2d776e14769e
parent2aa6aa62c6182317679596f7372dde6ee3665d15 (diff)
downloadbinaryen-72c035e905b3695f2763fdeb21163003d8595887.tar.gz
binaryen-72c035e905b3695f2763fdeb21163003d8595887.tar.bz2
binaryen-72c035e905b3695f2763fdeb21163003d8595887.zip
[wasm-type][NFC] Encapsulate type canonicalization in a TypeStore (#3403)
Although there is only one "type store" right now, a subsequent PR will add a new "TypeBuilder" class that manages its own universe of temporary types. Rather than duplicate all the logic behind type creation and canonicalization, it makes more sense to encapsulate that logic in a class that TypeBuilder will be able to reuse.
-rw-r--r--src/wasm/wasm-type.cpp184
1 files changed, 96 insertions, 88 deletions
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 7de274e9c..4c506beda 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -232,105 +232,113 @@ namespace wasm {
namespace {
-std::mutex mutex;
-
-// Track unique_ptrs for constructed types to avoid leaks
-std::vector<std::unique_ptr<TypeInfo>> constructedTypes;
-
-// Maps from constructed types to the canonical Type ID.
-std::unordered_map<TypeInfo, uintptr_t> indices = {
- // If a Type is constructed from a list of types, the list of types becomes
- // implicitly converted to a TypeInfo before canonicalizing its id. This is
- // also the case if a list of just one type is provided, even though such a
- // list of types will be canonicalized to the BasicID of the single type. As
- // such, the following entries are solely placeholders to enable the lookup
- // of lists of just one type to the BasicID of the single type.
- {TypeInfo(Tuple()), Type::none},
- {TypeInfo({Type::unreachable}), Type::unreachable},
- {TypeInfo({Type::i32}), Type::i32},
- {TypeInfo({Type::i64}), Type::i64},
- {TypeInfo({Type::f32}), Type::f32},
- {TypeInfo({Type::f64}), Type::f64},
- {TypeInfo({Type::v128}), Type::v128},
- {TypeInfo({Type::funcref}), Type::funcref},
- {TypeInfo(HeapType(HeapType::FuncKind), true), Type::funcref},
- {TypeInfo({Type::externref}), Type::externref},
- {TypeInfo(HeapType(HeapType::ExternKind), true), Type::externref},
- {TypeInfo({Type::exnref}), Type::exnref},
- {TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref},
- {TypeInfo({Type::anyref}), Type::anyref},
- {TypeInfo(HeapType(HeapType::AnyKind), true), Type::anyref},
- {TypeInfo({Type::eqref}), Type::eqref},
- {TypeInfo(HeapType(HeapType::EqKind), true), Type::eqref},
- {TypeInfo({Type::i31ref}), Type::i31ref},
- {TypeInfo(HeapType(HeapType::I31Kind), false), Type::i31ref},
-};
-
-} // anonymous namespace
+struct TypeStore {
+ std::mutex mutex;
+
+ // Track unique_ptrs for constructed types to avoid leaks
+ std::vector<std::unique_ptr<TypeInfo>> constructedTypes;
+
+ // Maps from constructed types to the canonical Type ID.
+ std::unordered_map<TypeInfo, uintptr_t> indices = {
+ // If a Type is constructed from a list of types, the list of types becomes
+ // implicitly converted to a TypeInfo before canonicalizing its id. This is
+ // also the case if a list of just one type is provided, even though such a
+ // list of types will be canonicalized to the BasicID of the single type. As
+ // such, the following entries are solely placeholders to enable the lookup
+ // of lists of just one type to the BasicID of the single type.
+ {TypeInfo(Tuple()), Type::none},
+ {TypeInfo({Type::unreachable}), Type::unreachable},
+ {TypeInfo({Type::i32}), Type::i32},
+ {TypeInfo({Type::i64}), Type::i64},
+ {TypeInfo({Type::f32}), Type::f32},
+ {TypeInfo({Type::f64}), Type::f64},
+ {TypeInfo({Type::v128}), Type::v128},
+ {TypeInfo({Type::funcref}), Type::funcref},
+ {TypeInfo(HeapType(HeapType::FuncKind), true), Type::funcref},
+ {TypeInfo({Type::externref}), Type::externref},
+ {TypeInfo(HeapType(HeapType::ExternKind), true), Type::externref},
+ {TypeInfo({Type::exnref}), Type::exnref},
+ {TypeInfo(HeapType(HeapType::ExnKind), true), Type::exnref},
+ {TypeInfo({Type::anyref}), Type::anyref},
+ {TypeInfo(HeapType(HeapType::AnyKind), true), Type::anyref},
+ {TypeInfo({Type::eqref}), Type::eqref},
+ {TypeInfo(HeapType(HeapType::EqKind), true), Type::eqref},
+ {TypeInfo({Type::i31ref}), Type::i31ref},
+ {TypeInfo(HeapType(HeapType::I31Kind), false), Type::i31ref},
+ };
-static uintptr_t canonicalize(const TypeInfo& info) {
- std::lock_guard<std::mutex> lock(mutex);
- auto indexIt = indices.find(info);
- if (indexIt != indices.end()) {
- return indexIt->second;
+ uintptr_t canonicalize(const TypeInfo& info) {
+ std::lock_guard<std::mutex> lock(mutex);
+ auto indexIt = indices.find(info);
+ if (indexIt != indices.end()) {
+ return indexIt->second;
+ }
+ auto ptr = std::make_unique<TypeInfo>(info);
+ auto id = uintptr_t(ptr.get());
+ constructedTypes.push_back(std::move(ptr));
+ assert(id > Type::_last_basic_id);
+ indices[info] = id;
+ return id;
}
- auto ptr = std::make_unique<TypeInfo>(info);
- auto id = uintptr_t(ptr.get());
- constructedTypes.push_back(std::move(ptr));
- assert(id > Type::_last_basic_id);
- indices[info] = id;
- return id;
-}
-
-static TypeInfo* getTypeInfo(const Type& type) {
- return (TypeInfo*)type.getID();
-}
-
-Type::Type(std::initializer_list<Type> types) : Type(Tuple(types)) {}
-Type::Type(const Tuple& tuple) {
- auto& types = tuple.types;
+ Type makeType(const Tuple& tuple) {
+ auto& types = tuple.types;
#ifndef NDEBUG
- for (Type t : types) {
- assert(t.isSingle());
- }
+ for (Type t : types) {
+ assert(t.isSingle());
+ }
#endif
- if (types.size() == 0) {
- id = none;
- return;
- }
- if (types.size() == 1) {
- *this = types[0];
- return;
+ if (types.size() == 0) {
+ return Type::none;
+ }
+ if (types.size() == 1) {
+ return types[0];
+ }
+ return Type(canonicalize(TypeInfo(tuple)));
}
- id = canonicalize(TypeInfo(tuple));
-}
-Type::Type(const HeapType& heapType, bool nullable) {
+ Type makeType(const HeapType& heapType, bool nullable) {
#ifndef NDEBUG
- switch (heapType.kind) {
- case HeapType::FuncKind:
- case HeapType::ExternKind:
- case HeapType::AnyKind:
- case HeapType::EqKind:
- case HeapType::I31Kind:
- case HeapType::ExnKind:
- case HeapType::SignatureKind:
- break;
- case HeapType::StructKind:
- for (Field f : heapType.struct_.fields) {
- assert(f.type.isSingle());
- }
- break;
- case HeapType::ArrayKind:
- assert(heapType.array.element.type.isSingle());
- break;
- }
+ switch (heapType.kind) {
+ case HeapType::FuncKind:
+ case HeapType::ExternKind:
+ case HeapType::AnyKind:
+ case HeapType::EqKind:
+ case HeapType::I31Kind:
+ case HeapType::ExnKind:
+ case HeapType::SignatureKind:
+ break;
+ case HeapType::StructKind:
+ for (Field f : heapType.struct_.fields) {
+ assert(f.type.isSingle());
+ }
+ break;
+ case HeapType::ArrayKind:
+ assert(heapType.array.element.type.isSingle());
+ break;
+ }
#endif
- id = canonicalize(TypeInfo(heapType, nullable));
+ return Type(canonicalize(TypeInfo(heapType, nullable)));
+ }
+
+ Type makeType(const Rtt& rtt) { return Type(canonicalize(TypeInfo(rtt))); }
+};
+
+TypeStore globalTypeStore;
+
+TypeInfo* getTypeInfo(const Type& type) { return (TypeInfo*)type.getID(); }
+
+} // anonymous namespace
+
+Type::Type(std::initializer_list<Type> types) : Type(Tuple(types)) {}
+
+Type::Type(const Tuple& tuple) { *this = globalTypeStore.makeType(tuple); }
+
+Type::Type(const HeapType& heapType, bool nullable) {
+ *this = globalTypeStore.makeType(heapType, nullable);
}
-Type::Type(const Rtt& rtt) { id = canonicalize(TypeInfo(rtt)); }
+Type::Type(const Rtt& rtt) { *this = globalTypeStore.makeType(rtt); }
bool Type::isTuple() const {
if (isBasic()) {