@@ -501,6 +501,12 @@ struct CollectedFuncInfo {
501
501
// when we update the child we can find the parent and handle any special
502
502
// behavior we need there.
503
503
std::unordered_map<Expression*, Expression*> childParents;
504
+
505
+ // All functions that might be called from the outside. Any RefFunc suggests
506
+ // that, in open world. (We could be more precise and use our flow analysis to
507
+ // see which, in fact, flow outside, but it is unclear how useful that would
508
+ // be. Anyhow, closed-world is more important to optimize, and avoids this.)
509
+ std::unordered_set<Name> calledFromOutside;
504
510
};
505
511
506
512
// Does a walk while maintaining a map of names of branch targets to those
@@ -528,8 +534,10 @@ struct BreakTargetWalker : public PostWalker<SubType, VisitorType> {
528
534
struct InfoCollector
529
535
: public BreakTargetWalker<InfoCollector, OverriddenVisitor<InfoCollector>> {
530
536
CollectedFuncInfo& info;
537
+ const PassOptions& options;
531
538
532
- InfoCollector (CollectedFuncInfo& info) : info(info) {}
539
+ InfoCollector (CollectedFuncInfo& info, const PassOptions& options)
540
+ : info(info), options(options) {}
533
541
534
542
// Check if a type is relevant for us. If not, we can ignore it entirely.
535
543
bool isRelevant (Type type) {
@@ -665,6 +673,10 @@ struct InfoCollector
665
673
info.links .push_back (
666
674
{ResultLocation{func, i}, SignatureResultLocation{func->type , i}});
667
675
}
676
+
677
+ if (!options.closedWorld ) {
678
+ info.calledFromOutside .insert (curr->func );
679
+ }
668
680
}
669
681
void visitRefEq (RefEq* curr) {
670
682
addRoot (curr);
@@ -2092,7 +2104,7 @@ Flower::Flower(Module& wasm, const PassOptions& options)
2092
2104
// First, collect information from each function.
2093
2105
ModuleUtils::ParallelFunctionAnalysis<CollectedFuncInfo> analysis (
2094
2106
wasm, [&](Function* func, CollectedFuncInfo& info) {
2095
- InfoCollector finder (info);
2107
+ InfoCollector finder (info, options );
2096
2108
2097
2109
if (func->imported ()) {
2098
2110
// Imports return unknown values.
@@ -2114,7 +2126,7 @@ Flower::Flower(Module& wasm, const PassOptions& options)
2114
2126
// Also walk the global module code (for simplicity, also add it to the
2115
2127
// function map, using a "function" key of nullptr).
2116
2128
auto & globalInfo = analysis.map [nullptr ];
2117
- InfoCollector finder (globalInfo);
2129
+ InfoCollector finder (globalInfo, options );
2118
2130
finder.walkModuleCode (&wasm);
2119
2131
2120
2132
#ifdef POSSIBLE_CONTENTS_DEBUG
@@ -2153,6 +2165,16 @@ Flower::Flower(Module& wasm, const PassOptions& options)
2153
2165
// above.
2154
2166
InsertOrderedMap<Location, PossibleContents> roots;
2155
2167
2168
+ // Any function that may be called from the outside, like an export, is a
2169
+ // root, since they can be called with unknown parameters.
2170
+ auto calledFromOutside = [&](Name funcName) {
2171
+ auto * func = wasm.getFunction (funcName);
2172
+ auto params = func->getParams ();
2173
+ for (Index i = 0 ; i < func->getParams ().size (); i++) {
2174
+ roots[ParamLocation{func, i}] = PossibleContents::fromType (params[i]);
2175
+ }
2176
+ };
2177
+
2156
2178
for (auto & [func, info] : analysis.map ) {
2157
2179
for (auto & link : info.links ) {
2158
2180
links.insert (getIndexes (link));
@@ -2171,6 +2193,10 @@ Flower::Flower(Module& wasm, const PassOptions& options)
2171
2193
childParents[getIndex (ExpressionLocation{child, 0 })] =
2172
2194
getIndex (ExpressionLocation{parent, 0 });
2173
2195
}
2196
+
2197
+ for (auto func : info.calledFromOutside ) {
2198
+ calledFromOutside (func);
2199
+ }
2174
2200
}
2175
2201
2176
2202
// We no longer need the function-level info.
@@ -2180,16 +2206,7 @@ Flower::Flower(Module& wasm, const PassOptions& options)
2180
2206
std::cout << " external phase\n " ;
2181
2207
#endif
2182
2208
2183
- // Parameters of exported functions are roots, since exports can have callers
2184
- // that we can't see, so anything might arrive there.
2185
- auto calledFromOutside = [&](Name funcName) {
2186
- auto * func = wasm.getFunction (funcName);
2187
- auto params = func->getParams ();
2188
- for (Index i = 0 ; i < func->getParams ().size (); i++) {
2189
- roots[ParamLocation{func, i}] = PossibleContents::fromType (params[i]);
2190
- }
2191
- };
2192
-
2209
+ // Exports can be modified from the outside.
2193
2210
for (auto & ex : wasm.exports ) {
2194
2211
if (ex->kind == ExternalKind::Function) {
2195
2212
calledFromOutside (ex->value );
0 commit comments