diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-type.cpp | 70 |
1 files changed, 36 insertions, 34 deletions
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index d05af96a7..89592fc37 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -1403,12 +1403,20 @@ bool HeapType::isSubType(HeapType left, HeapType right) { return SubTyper().isSubType(left, right); } -std::vector<HeapType> HeapType::getHeapTypeChildren() { +std::vector<HeapType> HeapType::getHeapTypeChildren() const { HeapTypeChildCollector collector; - collector.walkRoot(this); + collector.walkRoot(const_cast<HeapType*>(this)); return collector.children; } +std::vector<HeapType> HeapType::getReferencedHeapTypes() const { + auto types = getHeapTypeChildren(); + if (auto super = getSuperType()) { + types.push_back(*super); + } + return types; +} + HeapType HeapType::getLeastUpperBound(HeapType a, HeapType b) { return TypeBounder().getLeastUpperBound(a, b); } @@ -1567,7 +1575,8 @@ bool SubTyper::isSubType(HeapType a, HeapType b) { // Basic HeapTypes are never subtypes of compound HeapTypes. return false; } - if (typeSystem == TypeSystem::Nominal) { + if (typeSystem == TypeSystem::Nominal || + typeSystem == TypeSystem::Isorecursive) { // Subtyping must be declared in a nominal system, not derived from // structure, so we will not recurse. TODO: optimize this search with some // form of caching. @@ -2402,7 +2411,12 @@ size_t RecGroupHasher::hash(HeapType type) const { // an index into a rec group. Only take the rec group identity into account if // the child is not a member of the top-level group because in that case the // group may not be canonicalized yet. - size_t digest = wasm::hash(type.getRecGroupIndex()); + size_t digest = wasm::hash(type.isBasic()); + if (type.isBasic()) { + wasm::rehash(digest, type.getID()); + return digest; + } + wasm::rehash(digest, type.getRecGroupIndex()); auto currGroup = type.getRecGroup(); if (currGroup != group) { wasm::rehash(digest, currGroup.getID()); @@ -2525,6 +2539,9 @@ bool RecGroupEquator::eq(HeapType a, HeapType b) const { // be canonicalized, explicitly check whether `a` and `b` are in the // respective recursion groups of the respective top-level groups we are // comparing, in which case the structure is still equivalent. + if (a.isBasic() || b.isBasic()) { + return a == b; + } if (a.getRecGroupIndex() != b.getRecGroupIndex()) { return false; } @@ -3526,22 +3543,9 @@ void canonicalizeEquirecursive(CanonicalizationState& state) { info->supertype = nullptr; } -#if TIME_CANONICALIZATION - auto start = std::chrono::steady_clock::now(); -#endif - // Canonicalize the shape of the type definition graph. ShapeCanonicalizer minimized(state.results); state.update(minimized.replacements); - -#if TIME_CANONICALIZATION - auto end = std::chrono::steady_clock::now(); - std::cerr << "Shape canonicalization: " - << std::chrono::duration_cast<std::chrono::milliseconds>(end - - start) - .count() - << " ms\n"; -#endif } std::optional<TypeBuilder::Error> @@ -3597,10 +3601,6 @@ canonicalizeNominal(CanonicalizationState& state) { // Nominal types do not require separate canonicalization, so just validate // that their subtyping is correct. -#if TIME_CANONICALIZATION - auto start = std::chrono::steady_clock::now(); -#endif - // Ensure there are no cycles in the subtype graph. This is the classic DFA // algorithm for detecting cycles, but in the form of a simple loop because // each node (type) has at most one child (supertype). @@ -3627,14 +3627,6 @@ canonicalizeNominal(CanonicalizationState& state) { return {*error}; } -#if TIME_CANONICALIZATION - auto end = std::chrono::steady_clock::now(); - std::cerr << "Validating subtyping took " - << std::chrono::duration_cast<std::chrono::milliseconds>(end - - start) - .count() - << " ms\n"; -#endif return {}; } @@ -3802,6 +3794,15 @@ TypeBuilder::BuildResult TypeBuilder::build() { state.dump(); #endif +#if TIME_CANONICALIZATION + using instant_t = std::chrono::time_point<std::chrono::steady_clock>; + auto getMillis = [&](instant_t start, instant_t end) { + return std::chrono::duration_cast<std::chrono::milliseconds>(end - start) + .count(); + }; + auto start = std::chrono::steady_clock::now(); +#endif + switch (typeSystem) { case TypeSystem::Equirecursive: canonicalizeEquirecursive(state); @@ -3819,18 +3820,19 @@ TypeBuilder::BuildResult TypeBuilder::build() { } #if TIME_CANONICALIZATION - auto start = std::chrono::steady_clock::now(); + auto afterStructureCanonicalization = std::chrono::steady_clock::now(); #endif globallyCanonicalize(state); #if TIME_CANONICALIZATION auto end = std::chrono::steady_clock::now(); - std::cerr << "Global canonicalization took " - << std::chrono::duration_cast<std::chrono::milliseconds>(end - - start) - .count() + std::cerr << "Total canonicalization time was " << getMillis(start, end) << " ms\n"; + std::cerr << "Structure canonicalization took " + << getMillis(start, afterStructureCanonicalization) << " ms\n"; + std::cerr << "Global canonicalization took " + << getMillis(afterStructureCanonicalization, end) << " ms\n"; #endif // Note built signature types. See comment in `HeapType::HeapType(Signature)`. |