summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-03-30 16:50:13 -0700
committerGitHub <noreply@github.com>2021-03-30 16:50:13 -0700
commit330f722a4f4ae5288b21954aefa496af5cbc71e7 (patch)
tree1c4dad7ff80f8dd5069d005c568d9142da5a2341 /src
parent38d73857a6a1ed6a404f393e69f838977dc27e83 (diff)
downloadbinaryen-330f722a4f4ae5288b21954aefa496af5cbc71e7.tar.gz
binaryen-330f722a4f4ae5288b21954aefa496af5cbc71e7.tar.bz2
binaryen-330f722a4f4ae5288b21954aefa496af5cbc71e7.zip
Scan all module-level code in collectHeapTypes() (#3752)
The key fix here is to call walkModuleCode so that we pick up on types that appear only in the table and nowhere else. The rest of the patch refactors the code so that that is practical.
Diffstat (limited to 'src')
-rw-r--r--src/ir/module-utils.h86
1 files changed, 42 insertions, 44 deletions
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h
index a87daee9e..666718c92 100644
--- a/src/ir/module-utils.h
+++ b/src/ir/module-utils.h
@@ -476,65 +476,63 @@ inline void collectHeapTypes(Module& wasm,
}
};
- // Collect the type use counts for a single function
- auto updateCounts = [&](Function* func, Counts& counts) {
- if (func->imported()) {
- return;
- }
- struct TypeCounter
- : PostWalker<TypeCounter, UnifiedExpressionVisitor<TypeCounter>> {
- Counts& counts;
-
- TypeCounter(Counts& counts) : counts(counts) {}
-
- void visitExpression(Expression* curr) {
- if (auto* call = curr->dynCast<CallIndirect>()) {
- counts.note(call->sig);
- } else if (curr->is<RefNull>()) {
+ struct CodeScanner
+ : PostWalker<CodeScanner, UnifiedExpressionVisitor<CodeScanner>> {
+ Counts& counts;
+
+ CodeScanner(Counts& counts) : counts(counts) {}
+
+ void visitExpression(Expression* curr) {
+ if (auto* call = curr->dynCast<CallIndirect>()) {
+ counts.note(call->sig);
+ } else if (curr->is<RefNull>()) {
+ counts.maybeNote(curr->type);
+ } else if (curr->is<RttCanon>() || curr->is<RttSub>()) {
+ counts.note(curr->type.getRtt().heapType);
+ } else if (auto* get = curr->dynCast<StructGet>()) {
+ counts.maybeNote(get->ref->type);
+ } else if (auto* set = curr->dynCast<StructSet>()) {
+ counts.maybeNote(set->ref->type);
+ } else if (Properties::isControlFlowStructure(curr)) {
+ if (curr->type.isTuple()) {
+ // TODO: Allow control flow to have input types as well
+ counts.note(Signature(Type::none, curr->type));
+ } else {
counts.maybeNote(curr->type);
- } else if (curr->is<RttCanon>() || curr->is<RttSub>()) {
- counts.note(curr->type.getRtt().heapType);
- } else if (auto* get = curr->dynCast<StructGet>()) {
- counts.maybeNote(get->ref->type);
- } else if (auto* set = curr->dynCast<StructSet>()) {
- counts.maybeNote(set->ref->type);
- } else if (Properties::isControlFlowStructure(curr)) {
- if (curr->type.isTuple()) {
- // TODO: Allow control flow to have input types as well
- counts.note(Signature(Type::none, curr->type));
- } else {
- counts.maybeNote(curr->type);
- }
}
}
- };
- TypeCounter(counts).walk(func->body);
+ }
};
- ModuleUtils::ParallelFunctionAnalysis<Counts> analysis(wasm, updateCounts);
-
- // Collect all the counts.
+ // Collect module-level info.
Counts counts;
- for (auto& curr : wasm.functions) {
- counts.note(curr->sig);
- for (auto type : curr->vars) {
- for (auto t : type) {
- counts.maybeNote(t);
- }
- }
- }
+ CodeScanner(counts).walkModuleCode(&wasm);
for (auto& curr : wasm.events) {
counts.note(curr->sig);
}
- for (auto& curr : wasm.globals) {
- counts.maybeNote(curr->type);
- }
+
+ // Collect info from functions in parallel.
+ ModuleUtils::ParallelFunctionAnalysis<Counts> analysis(
+ wasm, [&](Function* func, Counts& counts) {
+ counts.note(func->sig);
+ for (auto type : func->vars) {
+ for (auto t : type) {
+ counts.maybeNote(t);
+ }
+ }
+ if (!func->imported()) {
+ CodeScanner(counts).walk(func->body);
+ }
+ });
+
+ // Combine the function info with the module info.
for (auto& pair : analysis.map) {
Counts& functionCounts = pair.second;
for (auto& innerPair : functionCounts) {
counts[innerPair.first] += innerPair.second;
}
}
+
// A generic utility to traverse the child types of a type.
// TODO: work with tlively to refactor this to a shared place
auto walkRelevantChildren = [&](HeapType type, auto callback) {