summaryrefslogtreecommitdiff
path: root/src/emscripten-optimizer
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2019-04-24 10:22:56 -0700
committerGitHub <noreply@github.com>2019-04-24 10:22:56 -0700
commitf81c78bd62548a1eabc27adfbcbdc44cefb320cf (patch)
tree34db3cb4614640334342e11f3a24321e16422aff /src/emscripten-optimizer
parent5d3fcffdd9f9d9de10a0ce60d1e0163693c007c3 (diff)
downloadbinaryen-f81c78bd62548a1eabc27adfbcbdc44cefb320cf.tar.gz
binaryen-f81c78bd62548a1eabc27adfbcbdc44cefb320cf.tar.bz2
binaryen-f81c78bd62548a1eabc27adfbcbdc44cefb320cf.zip
wasm2js: start to optionally optimize the JS (#2046)
Removes redundant | 0s and similar things. (Apparently closure compiler doesn't do that, so makes sense to do here.)
Diffstat (limited to 'src/emscripten-optimizer')
-rw-r--r--src/emscripten-optimizer/optimizer.h11
-rw-r--r--src/emscripten-optimizer/simple_ast.cpp211
-rw-r--r--src/emscripten-optimizer/simple_ast.h13
3 files changed, 45 insertions, 190 deletions
diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h
index 12d7c1433..f6b3aa536 100644
--- a/src/emscripten-optimizer/optimizer.h
+++ b/src/emscripten-optimizer/optimizer.h
@@ -27,17 +27,6 @@ extern bool preciseF32,
extern cashew::Ref extraInfo;
-void eliminateDeadFuncs(cashew::Ref ast);
-void eliminate(cashew::Ref ast, bool memSafe=false);
-void eliminateMemSafe(cashew::Ref ast);
-void simplifyExpressions(cashew::Ref ast);
-void optimizeFrounds(cashew::Ref ast);
-void simplifyIfs(cashew::Ref ast);
-void registerize(cashew::Ref ast);
-void registerizeHarder(cashew::Ref ast);
-void minifyLocals(cashew::Ref ast);
-void asmLastOpts(cashew::Ref ast);
-
//
enum AsmType {
diff --git a/src/emscripten-optimizer/simple_ast.cpp b/src/emscripten-optimizer/simple_ast.cpp
index c9659f964..d6dc5e51a 100644
--- a/src/emscripten-optimizer/simple_ast.cpp
+++ b/src/emscripten-optimizer/simple_ast.cpp
@@ -183,189 +183,64 @@ void dump(const char *str, Ref node, bool pretty) {
std::cerr << std::endl;
}
-// AST traversals
-
// Traversals
struct TraverseInfo {
TraverseInfo() = default;
- TraverseInfo(Ref node, ArrayStorage* arr) : node(node), arr(arr), index(0) {}
- Ref node;
- ArrayStorage* arr;
- int index;
-};
-
-template<class T, int init>
-struct StackedStack { // a stack, on the stack
- T stackStorage[init];
- T* storage;
- int used = 0;
- int available = init; // used amount, available amount
- bool alloced = false;
-
- StackedStack() {
- storage = stackStorage;
- }
- ~StackedStack() {
- if (alloced) free(storage);
- }
-
- int size() { return used; }
-
- void push_back(const T& t) {
- assert(used <= available);
- if (used == available) {
- available *= 2;
- if (!alloced) {
- T* old = storage;
- storage = (T*)malloc(sizeof(T)*available);
- memcpy(storage, old, sizeof(T)*used);
- alloced = true;
- } else {
- T *newStorage = (T*)realloc(storage, sizeof(T)*available);
- assert(newStorage);
- storage = newStorage;
- }
- }
- assert(used < available);
- assert(storage);
- storage[used++] = t;
- }
-
- T& back() {
- assert(used > 0);
- return storage[used-1];
- }
-
- void pop_back() {
- assert(used > 0);
- used--;
- }
-};
-
-#define visitable(node) (node->isArray() && node->size() > 0)
-
-#define TRAV_STACK 40
-
-// Traverse, calling visit before the children
-void traversePre(Ref node, std::function<void (Ref)> visit) {
- if (!visitable(node)) return;
- visit(node);
- StackedStack<TraverseInfo, TRAV_STACK> stack;
- int index = 0;
- ArrayStorage* arr = &node->getArray();
- int arrsize = (int)arr->size();
- Ref* arrdata = &(*arr)[0];
- stack.push_back(TraverseInfo(node, arr));
- while (1) {
- if (index < arrsize) {
- Ref sub = *(arrdata+index);
- index++;
- if (visitable(sub)) {
- stack.back().index = index;
- index = 0;
- visit(sub);
- arr = &sub->getArray();
- arrsize = (int)arr->size();
- arrdata = &(*arr)[0];
- stack.push_back(TraverseInfo(sub, arr));
+ TraverseInfo(Ref node) : node(node) {
+ assert(node.get());
+ if (node->isArray()) {
+ for (size_t i = 0; i < node->size(); i++) {
+ maybeAdd(node[i]);
}
+ } else if (node->isAssign()) {
+ auto assign = node->asAssign();
+ maybeAdd(assign->target());
+ maybeAdd(assign->value());
+ } else if (node->isAssignName()) {
+ auto assign = node->asAssignName();
+ maybeAdd(assign->value());
} else {
- stack.pop_back();
- if (stack.size() == 0) break;
- TraverseInfo& back = stack.back();
- index = back.index;
- arr = back.arr;
- arrsize = (int)arr->size();
- arrdata = &(*arr)[0];
+ // no children
}
}
-}
+ Ref node;
+ size_t index = -1;
+ std::vector<Ref> children;
-// Traverse, calling visitPre before the children and visitPost after
-void traversePrePost(Ref node, std::function<void (Ref)> visitPre, std::function<void (Ref)> visitPost) {
- if (!visitable(node)) return;
- visitPre(node);
- StackedStack<TraverseInfo, TRAV_STACK> stack;
- int index = 0;
- ArrayStorage* arr = &node->getArray();
- int arrsize = (int)arr->size();
- Ref* arrdata = &(*arr)[0];
- stack.push_back(TraverseInfo(node, arr));
- while (1) {
- if (index < arrsize) {
- Ref sub = *(arrdata+index);
- index++;
- if (visitable(sub)) {
- stack.back().index = index;
- index = 0;
- visitPre(sub);
- arr = &sub->getArray();
- arrsize = (int)arr->size();
- arrdata = &(*arr)[0];
- stack.push_back(TraverseInfo(sub, arr));
- }
- } else {
- visitPost(stack.back().node);
- stack.pop_back();
- if (stack.size() == 0) break;
- TraverseInfo& back = stack.back();
- index = back.index;
- arr = back.arr;
- arrsize = (int)arr->size();
- arrdata = &(*arr)[0];
+private:
+ void maybeAdd(Ref child) {
+ if (child.get()) {
+ children.push_back(child);
}
}
-}
+};
-// Traverse, calling visitPre before the children and visitPost after. If pre returns false, do not traverse children
-void traversePrePostConditional(Ref node, std::function<bool (Ref)> visitPre, std::function<void (Ref)> visitPost) {
- if (!visitable(node)) return;
- if (!visitPre(node)) return;
- StackedStack<TraverseInfo, TRAV_STACK> stack;
- int index = 0;
- ArrayStorage* arr = &node->getArray();
- int arrsize = (int)arr->size();
- Ref* arrdata = &(*arr)[0];
- stack.push_back(TraverseInfo(node, arr));
- while (1) {
- if (index < arrsize) {
- Ref sub = *(arrdata+index);
- index++;
- if (visitable(sub)) {
- if (visitPre(sub)) {
- stack.back().index = index;
- index = 0;
- arr = &sub->getArray();
- arrsize = (int)arr->size();
- arrdata = &(*arr)[0];
- stack.push_back(TraverseInfo(sub, arr));
- }
+// Traverse, calling visit after the children
+void traversePost(Ref node, std::function<void (Ref)> visit) {
+ std::vector<TraverseInfo> stack;
+ stack.push_back(TraverseInfo(node));
+ while (!stack.empty()) {
+ TraverseInfo& back = stack.back();
+ if (back.index == size_t(-1)) {
+ // This is the first time we see this. Push its children.
+ back.index = 0;
+ for (auto child : back.children) {
+ stack.emplace_back(child);
}
- } else {
- visitPost(stack.back().node);
- stack.pop_back();
- if (stack.size() == 0) break;
- TraverseInfo& back = stack.back();
- index = back.index;
- arr = back.arr;
- arrsize = (int)arr->size();
- arrdata = &(*arr)[0];
+ continue;
}
- }
-}
-
-// Traverses all the top-level functions in the document
-void traverseFunctions(Ref ast, std::function<void (Ref)> visit) {
- if (!ast || ast->size() == 0) return;
- if (ast[0] == TOPLEVEL) {
- Ref stats = ast[1];
- for (size_t i = 0; i < stats->size(); i++) {
- Ref curr = stats[i];
- if (curr[0] == DEFUN) visit(curr);
+ if (back.index < back.children.size()) {
+ // Visit this child.
+ back.index++;
+ visit(back.children[back.index - 1]);
+ continue;
}
- } else if (ast[0] == DEFUN) {
- visit(ast);
+ assert(back.index == back.children.size());
+ // Time to visit the node itself
+ auto node = back.node;
+ stack.pop_back();
+ visit(node);
}
}
diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h
index e5e8c4e80..3d8508a15 100644
--- a/src/emscripten-optimizer/simple_ast.h
+++ b/src/emscripten-optimizer/simple_ast.h
@@ -527,17 +527,8 @@ struct AssignName : public Value {
// AST traversals
-// Traverse, calling visit before the children
-void traversePre(Ref node, std::function<void (Ref)> visit);
-
-// Traverse, calling visitPre before the children and visitPost after
-void traversePrePost(Ref node, std::function<void (Ref)> visitPre, std::function<void (Ref)> visitPost);
-
-// Traverse, calling visitPre before the children and visitPost after. If pre returns false, do not traverse children
-void traversePrePostConditional(Ref node, std::function<bool (Ref)> visitPre, std::function<void (Ref)> visitPost);
-
-// Traverses all the top-level functions in the document
-void traverseFunctions(Ref ast, std::function<void (Ref)> visit);
+// Traverse, calling visit after the children
+void traversePost(Ref node, std::function<void (Ref)> visit);
// JS printing support