summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2022-01-28 17:56:12 -0800
committerGitHub <noreply@github.com>2022-01-29 01:56:12 +0000
commit098e02abadefe0e227c3c88a36e93d083ce004a8 (patch)
tree8e04edb91b4d57f9776c86169c8cbf0f12b7b8c5 /src/wasm
parent019df9d734b463ad4d194f4241c5e4f077e07def (diff)
downloadbinaryen-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.cpp80
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 {