summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2018-12-13 15:45:21 -0800
committerGitHub <noreply@github.com>2018-12-13 15:45:21 -0800
commit0fd96e6b07f0a0907737c0f44e55060e057c2bb9 (patch)
tree62c169433f1dcf67644df59c102bb31852208b1d /src
parent802dd8ff76d423f438c1d69dd5da6c47bb762c88 (diff)
downloadbinaryen-0fd96e6b07f0a0907737c0f44e55060e057c2bb9.tar.gz
binaryen-0fd96e6b07f0a0907737c0f44e55060e057c2bb9.tar.bz2
binaryen-0fd96e6b07f0a0907737c0f44e55060e057c2bb9.zip
No exit runtime pass (#1816)
When emscripten knows that the runtime will not be exited, it can tell codegen to not emit atexit() calls (since those callbacks will never be run). This saves both code size and startup time. In asm2wasm the JSBackend does it directly. For the wasm backend, this pass does the same on the output wasm.
Diffstat (limited to 'src')
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/Inlining.cpp4
-rw-r--r--src/passes/MergeBlocks.cpp2
-rw-r--r--src/passes/Metrics.cpp4
-rw-r--r--src/passes/NoExitRuntime.cpp60
-rw-r--r--src/passes/pass.cpp1
-rw-r--r--src/passes/passes.h1
7 files changed, 68 insertions, 5 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index b4e396750..0ad9dbf05 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -30,6 +30,7 @@ SET(passes_SOURCES
Metrics.cpp
MinifyImportsAndExports.cpp
NameList.cpp
+ NoExitRuntime.cpp
OptimizeInstructions.cpp
PickLoadSigns.cpp
PostEmscripten.cpp
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index ebc33bf97..35afc5776 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -349,11 +349,11 @@ struct Inlining : public Pass {
}
};
-Pass *createInliningPass() {
+Pass* createInliningPass() {
return new Inlining();
}
-Pass *createInliningOptimizingPass() {
+Pass* createInliningOptimizingPass() {
auto* ret = new Inlining();
ret->optimize = true;
return ret;
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 57f8b7e41..38e9fc6a2 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -373,7 +373,7 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
Pass* create() override { return new MergeBlocks; }
- void visitBlock(Block *curr) {
+ void visitBlock(Block* curr) {
optimizeBlock(curr, getModule(), getPassOptions());
}
diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp
index 5176f8762..b794ea32d 100644
--- a/src/passes/Metrics.cpp
+++ b/src/passes/Metrics.cpp
@@ -194,11 +194,11 @@ struct Metrics : public WalkerPass<PostWalker<Metrics, UnifiedExpressionVisitor<
}
};
-Pass *createMetricsPass() {
+Pass* createMetricsPass() {
return new Metrics(false);
}
-Pass *createFunctionMetricsPass() {
+Pass* createFunctionMetricsPass() {
return new Metrics(true);
}
diff --git a/src/passes/NoExitRuntime.cpp b/src/passes/NoExitRuntime.cpp
new file mode 100644
index 000000000..d76bb34ba
--- /dev/null
+++ b/src/passes/NoExitRuntime.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Assumes the program will never exit the runtime (as in the emscripten
+// NO_EXIT_RUNTIME option). That means that atexit()s do not need to be
+// run.
+//
+
+#include <pass.h>
+#include <wasm.h>
+#include <wasm-builder.h>
+#include <asmjs/shared-constants.h>
+
+using namespace std;
+
+namespace wasm {
+
+struct NoExitRuntime : public WalkerPass<PostWalker<NoExitRuntime>> {
+ bool isFunctionParallel() override { return true; }
+
+ Pass* create() override { return new NoExitRuntime; }
+
+ void visitCall(Call* curr) {
+ auto* import = getModule()->getFunctionOrNull(curr->target);
+ if (!import || !import->imported() || import->module != ENV) return;
+ // Remove all possible manifestations of atexit, across asm2wasm and llvm wasm backend.
+ for (auto* name : {
+ "___cxa_atexit",
+ "_atexit",
+ "__cxa_atexit",
+ "atexit",
+ }) {
+ if (strcmp(name, import->base.str) == 0) {
+ replaceCurrent(
+ Builder(*getModule()).replaceWithIdenticalType(curr)
+ );
+ }
+ }
+ }
+};
+
+Pass* createNoExitRuntimePass() {
+ return new NoExitRuntime();
+}
+
+} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index c42a3d144..f250b7de6 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -98,6 +98,7 @@ void PassRegistry::registerPasses() {
registerPass("minify-imports", "minifies import names (only those, and not export names), and emits a mapping to the minified ones", createMinifyImportsPass);
registerPass("minify-imports-and-exports", "minifies both import and export names, and emits a mapping to the minified ones", createMinifyImportsAndExportsPass);
registerPass("nm", "name list", createNameListPass);
+ registerPass("no-exit-runtime", "removes calls to atexit(), which is valid if the C runtime will never be exited", createNoExitRuntimePass);
registerPass("optimize-instructions", "optimizes instruction combinations", createOptimizeInstructionsPass);
registerPass("optimize-stack-ir", "optimize Stack IR", createOptimizeStackIRPass);
registerPass("pick-load-signs", "pick load signs based on their uses", createPickLoadSignsPass);
diff --git a/src/passes/passes.h b/src/passes/passes.h
index 8f5ca7e0a..df4322eee 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -55,6 +55,7 @@ Pass* createMinifyImportsPass();
Pass* createMinifyImportsAndExportsPass();
Pass* createMetricsPass();
Pass* createNameListPass();
+Pass* createNoExitRuntimePass();
Pass* createOptimizeInstructionsPass();
Pass* createOptimizeStackIRPass();
Pass* createPickLoadSignsPass();