summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/module-splitting.cpp55
-rw-r--r--src/ir/module-splitting.h6
-rw-r--r--src/tools/wasm-split/split-options.cpp9
-rw-r--r--src/tools/wasm-split/split-options.h1
-rw-r--r--src/tools/wasm-split/wasm-split.cpp1
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);