diff options
author | Alon Zakai <alonzakai@gmail.com> | 2018-12-13 15:45:21 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-13 15:45:21 -0800 |
commit | 0fd96e6b07f0a0907737c0f44e55060e057c2bb9 (patch) | |
tree | 62c169433f1dcf67644df59c102bb31852208b1d /src | |
parent | 802dd8ff76d423f438c1d69dd5da6c47bb762c88 (diff) | |
download | binaryen-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.txt | 1 | ||||
-rw-r--r-- | src/passes/Inlining.cpp | 4 | ||||
-rw-r--r-- | src/passes/MergeBlocks.cpp | 2 | ||||
-rw-r--r-- | src/passes/Metrics.cpp | 4 | ||||
-rw-r--r-- | src/passes/NoExitRuntime.cpp | 60 | ||||
-rw-r--r-- | src/passes/pass.cpp | 1 | ||||
-rw-r--r-- | src/passes/passes.h | 1 |
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(); |