diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/module-splitting.cpp | 55 | ||||
-rw-r--r-- | src/ir/module-splitting.h | 6 | ||||
-rw-r--r-- | src/tools/wasm-split/split-options.cpp | 9 | ||||
-rw-r--r-- | src/tools/wasm-split/split-options.h | 1 | ||||
-rw-r--r-- | src/tools/wasm-split/wasm-split.cpp | 1 |
5 files changed, 50 insertions, 22 deletions
diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index 22f8b301f..adda1f4a6 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -94,10 +94,9 @@ template<class F> void forEachElement(Module& module, F f) { } else if (auto* g = segment->offset->dynCast<GlobalGet>()) { base = g->name; } - ElementUtils::iterElementSegmentFunctionNames( - segment, [&](Name& entry, Index i) { - f(segment->table, base, offset + i, entry); - }); + for (Index i = 0; i < segment->data.size(); ++i) { + f(segment->table, base, offset + i, segment->data[i]); + } }); } @@ -209,9 +208,12 @@ TableSlotManager::TableSlotManager(Module& module) : module(module) { } // Initialize funcIndices with the functions already in the table. - forEachElement(module, [&](Name table, Name base, Index offset, Name func) { - addSlot(func, {table, base, offset}); - }); + forEachElement(module, + [&](Name table, Name base, Index offset, Expression* elem) { + if (auto* func = elem->dynCast<RefFunc>()) { + addSlot(func->func, {table, base, offset}); + } + }); } Table* TableSlotManager::makeTable() { @@ -693,21 +695,32 @@ void ModuleSplitter::setupTablePatching() { // Replace table references to secondary functions with an imported // placeholder that encodes the table index in its name: // `importNamespace`.`index`. - forEachElement(primary, [&](Name, Name, Index index, Name& elem) { - if (secondaryFuncs.count(elem)) { - placeholderMap[index] = elem; - auto* secondaryFunc = secondary.getFunction(elem); - replacedElems[index] = secondaryFunc; - auto placeholder = std::make_unique<Function>(); - placeholder->module = config.placeholderNamespace; - placeholder->base = std::to_string(index); - placeholder->name = Names::getValidFunctionName( - primary, std::string("placeholder_") + placeholder->base.toString()); - placeholder->hasExplicitName = true; - placeholder->type = secondaryFunc->type; - elem = placeholder->name; - primary.addFunction(std::move(placeholder)); + forEachElement(primary, [&](Name, Name, Index index, Expression*& elem) { + auto* ref = elem->dynCast<RefFunc>(); + if (!ref) { + return; + } + if (!secondaryFuncs.count(ref->func)) { + return; + } + placeholderMap[index] = ref->func; + auto* secondaryFunc = secondary.getFunction(ref->func); + replacedElems[index] = secondaryFunc; + if (!config.usePlaceholders) { + // TODO: This can create active element segments with lots of nulls. We + // should optimize them like we do data segments with zeros. + elem = Builder(primary).makeRefNull(HeapType::nofunc); + return; } + auto placeholder = std::make_unique<Function>(); + placeholder->module = config.placeholderNamespace; + placeholder->base = std::to_string(index); + placeholder->name = Names::getValidFunctionName( + primary, std::string("placeholder_") + placeholder->base.toString()); + placeholder->hasExplicitName = true; + placeholder->type = secondaryFunc->type; + elem = Builder(primary).makeRefFunc(placeholder->name, placeholder->type); + primary.addFunction(std::move(placeholder)); }); if (replacedElems.size() == 0) { diff --git a/src/ir/module-splitting.h b/src/ir/module-splitting.h index dc5bb1998..620993d2d 100644 --- a/src/ir/module-splitting.h +++ b/src/ir/module-splitting.h @@ -52,11 +52,15 @@ struct Config { // exists. May or may not include imported functions, which are always kept in // the primary module regardless. std::set<Name> primaryFuncs; + // Whether to import placeholder functions into the primary module that will + // be called when a secondary function is called before the secondary module + // has been loaded. + bool usePlaceholders = true; // The namespace from which to import primary functions into the secondary // module. Name importNamespace = "primary"; // The namespace from which to import placeholder functions into the primary - // module. + // module. Ignored if `usePlaceholders` is false. Name placeholderNamespace = "placeholder"; // The prefix to attach to the name of any newly created exports. This can be // used to differentiate between "real" exports of the module and exports that diff --git a/src/tools/wasm-split/split-options.cpp b/src/tools/wasm-split/split-options.cpp index 9a9351998..825efddd9 100644 --- a/src/tools/wasm-split/split-options.cpp +++ b/src/tools/wasm-split/split-options.cpp @@ -177,6 +177,15 @@ WasmSplitOptions::WasmSplitOptions() Options::Arguments::Zero, [&](Options* o, const std::string& argument) { symbolMap = true; }) .add( + "--no-placeholders", + "", + "Do not import placeholder functions. Calls to secondary functions will " + "fail before the secondary module has been instantiated.", + WasmSplitOption, + {Mode::Split}, + Options::Arguments::Zero, + [&](Options* o, const std::string& argument) { usePlaceholders = false; }) + .add( "--placeholdermap", "", "Write a file mapping placeholder indices to the function names.", diff --git a/src/tools/wasm-split/split-options.h b/src/tools/wasm-split/split-options.h index 6aa5b0011..b8129f29b 100644 --- a/src/tools/wasm-split/split-options.h +++ b/src/tools/wasm-split/split-options.h @@ -41,6 +41,7 @@ struct WasmSplitOptions : ToolOptions { }; StorageKind storageKind = StorageKind::InGlobals; + bool usePlaceholders = true; bool unescape = false; bool verbose = false; bool emitBinary = true; diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index c1ec6052f..cb148090d 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -329,6 +329,7 @@ void splitModule(const WasmSplitOptions& options) { if (options.exportPrefix.size()) { config.newExportPrefix = options.exportPrefix; } + config.usePlaceholders = options.usePlaceholders; config.minimizeNewExportNames = !options.passOptions.debugInfo; config.jspi = options.jspi; auto splitResults = ModuleSplitting::splitFunctions(wasm, config); |