aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2011-12-22 16:10:11 -0800
committerAlon Zakai <alonzakai@gmail.com>2011-12-22 16:10:11 -0800
commitaa9985f119a8099a8eb0335de787d560242af4f9 (patch)
tree3a38d68a87b93abb2504fa958629807a2e4e7d5d
parent8f69b282df06f5c8800226c98776ea27fa1c7f00 (diff)
refactor vacuum out in js optimizer
-rw-r--r--tools/js-optimizer.js142
1 files changed, 74 insertions, 68 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 126637ec..44f560d5 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -357,6 +357,77 @@ function simplifyExpressionsPost(ast) {
simplifyNotComps(ast);
}
+// Clear out empty ifs and blocks, and redundant blocks/stats and so forth
+function vacuum(ast) {
+ var ret;
+ var more = true;
+ while (more) {
+ more = false;
+ ast[1].forEach(function(node, i) {
+ function simplifyList(node, i) {
+ var changed = false;
+ var pre = node[i].length;
+ node[i] = node[i].filter(function(blockItem) { return !jsonCompare(blockItem, emptyNode()) });
+ if (node[i].length < pre) changed = true;
+ // Also, seek blocks with single items we can simplify
+ node[i] = node[i].map(function(subNode) {
+ if (subNode[0] == 'block' && typeof subNode[1] == 'object' && subNode[1].length == 1 && subNode[1][0][0] == 'if') {
+ return subNode[1][0];
+ }
+ return subNode;
+ });
+ if (changed) {
+ more = true;
+ return node;
+ }
+ }
+ var type = node[0];
+ if (type == 'defun' && isGenerated(node[1])) {
+ traverse(node, function(node, type) {
+ if (type == 'if' && node[2][0] == 'block' && (!node[2][1] || node[2][1].length == 0)) {
+ more = true;
+ if (node[2][2]) { // if there is an else, return that
+ return node[2][2];
+ } else {
+ return emptyNode();
+ }
+ } else if (type == 'block' && !node[1]) {
+ return emptyNode();
+ } else if (type == 'block' && (node[1].length == 0 || (node[1].length == 1 && jsonCompare(node[1][0], emptyNode())))) {
+ more = true;
+ return emptyNode();
+ } else if (type == 'block' && node[1].length == 1 && node[1][0][0] == 'block') {
+ more = true;
+ return node[1][0];
+ } else if (type == 'stat' && node[1][0] == 'block') {
+ more = true;
+ return node[1];
+ } else if (type == 'block' && typeof node[1] == 'object') {
+ ret = simplifyList(node, 1);
+ if (ret) return ret;
+ } else if (type == 'defun' && node[3].length == 1 && node[3][0][0] == 'block') {
+ more = true;
+ node[3] = node[3][0][1];
+ return node;
+ } else if (type == 'defun') {
+ ret = simplifyList(node, 3);
+ if (ret) return ret;
+ } else if (type == 'do' && node[1][0] == 'num' && jsonCompare(node[2], emptyNode())) {
+ more = true;
+ return emptyNode();
+ } else if (type == 'label' && jsonCompare(node[2], emptyNode())) {
+ more = true;
+ return emptyNode();
+ } else if (type == 'if' && jsonCompare(node[3], emptyNode())) { // empty else clauses
+ node[3] = null;
+ return node;
+ }
+ });
+ }
+ });
+ }
+}
+
// Multiple blocks from the relooper are, in general, implemented by
// if (__label__ == x) { } else if ..
// and branching into them by
@@ -429,74 +500,7 @@ function hoistMultiples(ast) {
}
});
- // Clear out empty ifs and blocks, and redundant blocks/stats
- var ret;
- var more = true;
- while (more) {
- more = false;
- ast[1].forEach(function(node, i) {
- function simplifyList(node, i) {
- var changed = false;
- var pre = node[i].length;
- node[i] = node[i].filter(function(blockItem) { return !jsonCompare(blockItem, emptyNode()) });
- if (node[i].length < pre) changed = true;
- // Also, seek blocks with single items we can simplify
- node[i] = node[i].map(function(subNode) {
- if (subNode[0] == 'block' && typeof subNode[1] == 'object' && subNode[1].length == 1 && subNode[1][0][0] == 'if') {
- return subNode[1][0];
- }
- return subNode;
- });
- if (changed) {
- more = true;
- return node;
- }
- }
- var type = node[0];
- if (type == 'defun' && isGenerated(node[1])) {
- traverse(node, function(node, type) {
- if (type == 'if' && node[2][0] == 'block' && (!node[2][1] || node[2][1].length == 0)) {
- more = true;
- if (node[2][2]) { // if there is an else, return that
- return node[2][2];
- } else {
- return emptyNode();
- }
- } else if (type == 'block' && !node[1]) {
- return emptyNode();
- } else if (type == 'block' && (node[1].length == 0 || (node[1].length == 1 && jsonCompare(node[1][0], emptyNode())))) {
- more = true;
- return emptyNode();
- } else if (type == 'block' && node[1].length == 1 && node[1][0][0] == 'block') {
- more = true;
- return node[1][0];
- } else if (type == 'stat' && node[1][0] == 'block') {
- more = true;
- return node[1];
- } else if (type == 'block' && typeof node[1] == 'object') {
- ret = simplifyList(node, 1);
- if (ret) return ret;
- } else if (type == 'defun' && node[3].length == 1 && node[3][0][0] == 'block') {
- more = true;
- node[3] = node[3][0][1];
- return node;
- } else if (type == 'defun') {
- ret = simplifyList(node, 3);
- if (ret) return ret;
- } else if (type == 'do' && node[1][0] == 'num' && jsonCompare(node[2], emptyNode())) {
- more = true;
- return emptyNode();
- } else if (type == 'label' && jsonCompare(node[2], emptyNode())) {
- more = true;
- return emptyNode();
- } else if (type == 'if' && jsonCompare(node[3], emptyNode())) { // empty else clauses
- node[3] = null;
- return node;
- }
- });
- }
- });
- }
+ vacuum(ast);
}
// Simplifies loops
@@ -576,6 +580,8 @@ function loopOptimizer(ast) {
// TODO: pass 1: Removal of unneeded continues, breaks if they get us to where we are already going. That will
// help the next pass.
passTwo(ast);
+
+ vacuum(ast);
}
// Passes table