diff options
author | Alon Zakai <alonzakai@gmail.com> | 2019-04-24 10:22:56 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-24 10:22:56 -0700 |
commit | f81c78bd62548a1eabc27adfbcbdc44cefb320cf (patch) | |
tree | 34db3cb4614640334342e11f3a24321e16422aff /src/emscripten-optimizer | |
parent | 5d3fcffdd9f9d9de10a0ce60d1e0163693c007c3 (diff) | |
download | binaryen-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.h | 11 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.cpp | 211 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.h | 13 |
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 |