diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2022-01-28 17:56:12 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-29 01:56:12 +0000 |
commit | 098e02abadefe0e227c3c88a36e93d083ce004a8 (patch) | |
tree | 8e04edb91b4d57f9776c86169c8cbf0f12b7b8c5 /src/wasm | |
parent | 019df9d734b463ad4d194f4241c5e4f077e07def (diff) | |
download | binaryen-098e02abadefe0e227c3c88a36e93d083ce004a8.tar.gz binaryen-098e02abadefe0e227c3c88a36e93d083ce004a8.tar.bz2 binaryen-098e02abadefe0e227c3c88a36e93d083ce004a8.zip |
Isorecursive HeapType constructors (#4482)
Update the HeapType constructors that take Signature, Structs, and Arrays to
work properly with isorecursive typing. This is particularly important for the
Signature constructor, which is used frequently throughout the code base.
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-type.cpp | 80 |
1 files changed, 65 insertions, 15 deletions
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index b0b218189..d05af96a7 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -883,6 +883,18 @@ struct RecGroupStore { return canonical; } + // Utility for canonicalizing HeapTypes with trivial recursion groups. + HeapType insert(std::unique_ptr<HeapTypeInfo>&& info) { + std::lock_guard<std::mutex> lock(mutex); + assert(!info->recGroup && "Unexpected nontrivial rec group"); + auto group = asHeapType(info).getRecGroup(); + auto canonical = insert(group); + if (group == canonical) { + globalHeapTypeStore.insert(std::move(info)); + } + return canonical[0]; + } + void clear() { canonicalGroups.clear(); builtGroups.clear(); @@ -1232,19 +1244,27 @@ const Type& Type::Iterator::operator*() const { HeapType::HeapType(Signature sig) { assert(!isTemp(sig.params) && "Leaking temporary type!"); assert(!isTemp(sig.results) && "Leaking temporary type!"); - if (typeSystem == TypeSystem::Nominal) { - // Special case the creation of signature types in nominal mode to return a - // "canonical" type for the signature, which happens to be the first one - // created. We depend on being able to create new function signatures in - // many places, and historically they have always been structural, so - // creating a copy of an existing signature did not result in any code bloat - // or semantic changes. To avoid regressions or significant changes of - // behavior in nominal mode, we cache the canonical heap types for each - // signature to emulate structural behavior. - new (this) HeapType(nominalSignatureCache.getType(sig)); - } else { - new (this) HeapType(globalHeapTypeStore.insert(sig)); + switch (getTypeSystem()) { + case TypeSystem::Nominal: + // Special case the creation of signature types in nominal mode to return + // a "canonical" type for the signature, which happens to be the first one + // created. We depend on being able to create new function signatures in + // many places, and historically they have always been structural, so + // creating a copy of an existing signature did not result in any code + // bloat or semantic changes. To avoid regressions or significant changes + // of behavior in nominal mode, we cache the canonical heap types for each + // signature to emulate structural behavior. + new (this) HeapType(nominalSignatureCache.getType(sig)); + return; + case TypeSystem::Equirecursive: + new (this) HeapType(globalHeapTypeStore.insert(sig)); + return; + case TypeSystem::Isorecursive: + new (this) HeapType( + globalRecGroupStore.insert(std::make_unique<HeapTypeInfo>(sig))); + return; } + WASM_UNREACHABLE("unexpected type system"); } HeapType::HeapType(const Struct& struct_) { @@ -1253,7 +1273,17 @@ HeapType::HeapType(const Struct& struct_) { assert(!isTemp(field.type) && "Leaking temporary type!"); } #endif - new (this) HeapType(globalHeapTypeStore.insert(struct_)); + switch (getTypeSystem()) { + case TypeSystem::Nominal: + case TypeSystem::Equirecursive: + new (this) HeapType(globalHeapTypeStore.insert(struct_)); + return; + case TypeSystem::Isorecursive: + new (this) HeapType( + globalRecGroupStore.insert(std::make_unique<HeapTypeInfo>(struct_))); + return; + } + WASM_UNREACHABLE("unexpected type system"); } HeapType::HeapType(Struct&& struct_) { @@ -1262,12 +1292,32 @@ HeapType::HeapType(Struct&& struct_) { assert(!isTemp(field.type) && "Leaking temporary type!"); } #endif - new (this) HeapType(globalHeapTypeStore.insert(std::move(struct_))); + switch (getTypeSystem()) { + case TypeSystem::Nominal: + case TypeSystem::Equirecursive: + new (this) HeapType(globalHeapTypeStore.insert(std::move(struct_))); + return; + case TypeSystem::Isorecursive: + new (this) HeapType(globalRecGroupStore.insert( + std::make_unique<HeapTypeInfo>(std::move(struct_)))); + return; + } + WASM_UNREACHABLE("unexpected type system"); } HeapType::HeapType(Array array) { assert(!isTemp(array.element.type) && "Leaking temporary type!"); - new (this) HeapType(globalHeapTypeStore.insert(array)); + switch (getTypeSystem()) { + case TypeSystem::Nominal: + case TypeSystem::Equirecursive: + new (this) HeapType(globalHeapTypeStore.insert(array)); + return; + case TypeSystem::Isorecursive: + new (this) HeapType( + globalRecGroupStore.insert(std::make_unique<HeapTypeInfo>(array))); + return; + } + WASM_UNREACHABLE("unexpected type system"); } bool HeapType::isFunction() const { |