summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-04-26 17:39:14 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-04-26 17:39:14 -0700
commitdd778824cfc60c4478bbe7690769f444dad92803 (patch)
treeac664a729e5918c8ea19030ed45c0efe7bbf0ef9 /src
parent1b01c37546262069391e5a41e8a4a6daf2471a36 (diff)
downloadbinaryen-dd778824cfc60c4478bbe7690769f444dad92803.tar.gz
binaryen-dd778824cfc60c4478bbe7690769f444dad92803.tar.bz2
binaryen-dd778824cfc60c4478bbe7690769f444dad92803.zip
ast_utils improvements (#399)
* make EffectAnalyzer a little more fun to use * create a convert() method that can turn a node into a smaller node, reusing its memory, and use that in nop() * use convert in wasm-linker
Diffstat (limited to 'src')
-rw-r--r--src/ast_utils.h23
-rw-r--r--src/passes/RemoveUnusedBrs.cpp9
-rw-r--r--src/wasm-linker.cpp6
3 files changed, 25 insertions, 13 deletions
diff --git a/src/ast_utils.h b/src/ast_utils.h
index 55499d808..66dbf039a 100644
--- a/src/ast_utils.h
+++ b/src/ast_utils.h
@@ -49,6 +49,11 @@ struct BreakSeeker : public PostWalker<BreakSeeker, Visitor<BreakSeeker>> {
// TODO: optimize
struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer>> {
+ EffectAnalyzer() {}
+ EffectAnalyzer(Expression *ast) {
+ walk(ast);
+ }
+
bool branches = false;
bool calls = false;
std::set<Index> localsRead;
@@ -115,9 +120,21 @@ struct EffectAnalyzer : public PostWalker<EffectAnalyzer, Visitor<EffectAnalyzer
};
struct ExpressionManipulator {
- // Nop is the smallest node, so we can always nop-ify another node in our arena
- static void nop(Expression* target) {
- *static_cast<Nop*>(target) = Nop();
+ // Re-use a node's memory. This helps avoid allocation when optimizing.
+ template<typename InputType, typename OutputType>
+ static OutputType* convert(InputType *input) {
+ static_assert(sizeof(OutputType) <= sizeof(InputType),
+ "Can only convert to a smaller size Expression node");
+ input->~InputType(); // arena-allocaed, so no destructor, but avoid UB.
+ OutputType* output = (OutputType*)(input);
+ new (output) OutputType;
+ return output;
+ }
+
+ // Convenience method for nop, which is a common conversion
+ template<typename InputType>
+ static void nop(InputType* target) {
+ convert<InputType, Nop>(target);
}
};
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index f4efef173..5c21908a8 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -181,14 +181,11 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs, Visitor<R
if (curr->ifFalse) {
// if with else, consider turning it into a select if there is no control flow
// TODO: estimate cost
- EffectAnalyzer condition;
- condition.walk(curr->condition);
+ EffectAnalyzer condition(curr->condition);
if (!condition.hasSideEffects()) {
- EffectAnalyzer ifTrue;
- ifTrue.walk(curr->ifTrue);
+ EffectAnalyzer ifTrue(curr->ifTrue);
if (!ifTrue.hasSideEffects()) {
- EffectAnalyzer ifFalse;
- ifFalse.walk(curr->ifFalse);
+ EffectAnalyzer ifFalse(curr->ifFalse);
if (!ifFalse.hasSideEffects()) {
auto* select = getModule()->allocator.alloc<Select>();
select->condition = curr->condition;
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp
index 4fb7ea4ae..7524f439a 100644
--- a/src/wasm-linker.cpp
+++ b/src/wasm-linker.cpp
@@ -16,6 +16,7 @@
#include "wasm-linker.h"
#include "asm_v_wasm.h"
+#include "ast_utils.h"
#include "support/utilities.h"
#include "wasm-builder.h"
#include "wasm-printing.h"
@@ -64,12 +65,9 @@ void Linker::layout() {
// Change each call. The target is the same since it's still the name.
// Delete and re-allocate the Expression as CallImport to avoid undefined
// behavior.
- static_assert(sizeof(Call) >= sizeof(CallImport),
- "Cannot reallocate a CallImport in a Call arena slot");
for (auto* call : f.second) {
Call callCopy = std::move(*call);
- call->~Call();
- CallImport* newCall = new (call) CallImport;
+ CallImport* newCall = ExpressionManipulator::convert<Call, CallImport>(call);
newCall->type = callCopy.type;
newCall->operands = std::move(callCopy.operands);
newCall->target = target;