aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/js-optimizer.js57
-rw-r--r--tools/test-js-optimizer-output.js73
-rw-r--r--tools/test-js-optimizer.js66
3 files changed, 160 insertions, 36 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index d84c664a..a0595b88 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -239,7 +239,7 @@ function emptyNode() {
// Dump the AST. Useful for debugging. For example,
// node tools/js-optimizer.js ABSOLUTE_PATH_TO_FILE dumpAst
function dumpAst(ast) {
- printErr(JSON.stringify(ast));
+ printErr(JSON.stringify(ast, null, ' '));
}
function dumpSrc(ast) {
@@ -801,18 +801,24 @@ function vacuum(ast) {
if (node[0] == 'block' && (!node[1] || (typeof node[1] != 'object') || node[1].length == 0 || (node[1].length == 1 && isEmpty(node[1])))) return true;
return false;
}
- function simplifyList(node, i) {
+ function simplifyList(node, si) {
var changed = false;
- var pre = node[i].length;
- node[i] = node[i].filter(function(node) { return !isEmpty(node) });
- 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];
+ // Merge block items into this list, thus removing unneeded |{ .. }|'s
+ var statements = node[si];
+ var i = 0;
+ while (i < statements.length) {
+ var subNode = statements[i];
+ if (subNode[0] == 'block') {
+ statements.splice.apply(statements, [i, 1].concat(subNode[1] || []));
+ changed = true;
+ } else {
+ i++;
}
- return subNode;
- });
+ }
+ // Remove empty items
+ var pre = node[si].length;
+ node[si] = node[si].filter(function(node) { return !isEmpty(node) });
+ if (node[si].length < pre) changed = true;
if (changed) {
return node;
}
@@ -1002,6 +1008,35 @@ function hoistMultiples(ast) {
});
vacuum(ast);
+
+ // Afterpass: Reduce
+ // if (..) { .. break|continue } else { .. }
+ // to
+ // if (..) { .. break|continue } ..
+ traverseGenerated(ast, function(container, type) {
+ var statements = getStatements(container);
+ if (!statements) return;
+ for (var i = 0; i < statements.length; i++) {
+ var node = statements[i];
+ if (node[0] == 'if' && node[2][0] == 'block' && node[3] && node[3][0] == 'block') {
+ var stat1 = node[2][1], stat2 = node[3][1];
+ // If break|continue in the latter and not the former, reverse them
+ if (!(stat1[stat1.length-1][0] in LOOP_FLOW) && (stat2[stat2.length-1][0] in LOOP_FLOW)) {
+ var temp = node[3];
+ node[3] = node[2];
+ node[2] = temp;
+ node[1] = ['unary-prefix', '!', node[1]];
+ simplifyNotComps(node[1]); // bake the ! into the expression
+ stat1 = node[2][1];
+ stat2 = node[3][1];
+ }
+ if (stat1[stat1.length-1][0] in LOOP_FLOW) {
+ statements.splice.apply(statements, [i+1, 0].concat(stat2));
+ node[3] = null;
+ }
+ }
+ }
+ });
}
// Simplifies loops
diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js
index 17c06a95..ca76cae1 100644
--- a/tools/test-js-optimizer-output.js
+++ b/tools/test-js-optimizer-output.js
@@ -68,9 +68,7 @@ function loopy() {
something();
} while (0);
next();
- {
- something();
- }
+ something();
}
function ignoreLoopy() {
b$for_cond$4 : while (1) {
@@ -141,12 +139,11 @@ function hoisting() {
}
pause(7);
while (1) {
- if ($i < $N) {
- somethingElse();
- } else {
+ if ($i >= $N) {
__label__ = 3;
break;
}
+ somethingElse();
if ($i < $N) {
somethingElse();
}
@@ -166,15 +163,43 @@ function hoisting() {
}
__label__ = 39;
break;
- } else {
- __label__ = 38;
}
+ __label__ = 38;
} while (0);
if (__label__ == 38) {
var $79 = $_pr6;
}
pause(9);
var $cmp70 = ($call69 | 0) != 0;
+ pause(10);
+ while (check()) {
+ if ($i < $N) {
+ callOther();
+ break;
+ }
+ somethingElse();
+ if ($i1 < $N) {
+ callOther();
+ continue;
+ }
+ somethingElse();
+ if ($i2 >= $N) {
+ somethingElse();
+ break;
+ }
+ callOther();
+ if ($i3 >= $N) {
+ somethingElse();
+ continue;
+ }
+ callOther();
+ if ($i4 < $N) {
+ callOther();
+ break;
+ }
+ somethingElse();
+ continue;
+ }
}
function innerShouldAlsoBeHoisted() {
function hoisting() {
@@ -208,9 +233,7 @@ function sleep() {
}
function demangle($cmp) {
do {
- if ($cmp) {
- __label__ = 3;
- } else {
+ if (!$cmp) {
if (something()) {
__label__ = 3;
break;
@@ -218,6 +241,7 @@ function demangle($cmp) {
more();
break;
}
+ __label__ = 3;
} while (0);
if (__label__ == 3) {
final();
@@ -259,25 +283,21 @@ function moreLabels() {
}
if ($cmp1) {
break;
- } else {
- inc();
}
+ inc();
}
pause(999);
$while_body$$while_end$31 : do {
if ($cmp3) {
var $6 = $5;
- {
- while (1) {
- var $6;
- $iter = $6 + 3;
- if (FHEAP[$iter + 1] < $pct_addr) {
- var $6 = $iter;
- } else {
- var $_lcssa = $iter;
- break $while_body$$while_end$31;
- }
+ while (1) {
+ var $6;
+ $iter = $6 + 3;
+ if (FHEAP[$iter + 1] >= $pct_addr) {
+ var $_lcssa = $iter;
+ break $while_body$$while_end$31;
}
+ var $6 = $iter;
}
} else {
var $_lcssa = $5;
@@ -286,4 +306,9 @@ function moreLabels() {
var $_lcssa;
cheez();
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels"]
+function notComps() {
+ if (HEAP32[$incdec_ptr71_i + 8 >> 2] != 0) {
+ shoo();
+ }
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps"]
diff --git a/tools/test-js-optimizer.js b/tools/test-js-optimizer.js
index 95985bc8..18c9ac75 100644
--- a/tools/test-js-optimizer.js
+++ b/tools/test-js-optimizer.js
@@ -226,6 +226,65 @@ function hoisting() {
$if_then72$$if_end73$126 : do {
if (__label__ == 40) {} else if (__label__ == 41) {}
} while (0);
+ pause(10);
+ while(check()) {
+ if ($i < $N) {
+ __label__ = 2;
+ } else {
+ __label__ = 3;
+ }
+ if (__label__ == 2) {
+ callOther();
+ break;
+ } else if (__label__ == 3) {
+ somethingElse();
+ }
+ if ($i1 < $N) {
+ __label__ = 2;
+ } else {
+ __label__ = 3;
+ }
+ if (__label__ == 2) {
+ callOther();
+ continue;
+ } else if (__label__ == 3) {
+ somethingElse();
+ }
+ if ($i2 < $N) {
+ __label__ = 2;
+ } else {
+ __label__ = 3;
+ }
+ if (__label__ == 2) {
+ callOther();
+ } else if (__label__ == 3) {
+ somethingElse();
+ break;
+ }
+ if ($i3 < $N) {
+ __label__ = 2;
+ } else {
+ __label__ = 3;
+ }
+ if (__label__ == 2) {
+ callOther();
+ } else if (__label__ == 3) {
+ somethingElse();
+ continue;
+ }
+ if ($i4 < $N) {
+ __label__ = 2;
+ } else {
+ __label__ = 3;
+ }
+ if (__label__ == 2) {
+ callOther();
+ break;
+ } else if (__label__ == 3) {
+ somethingElse();
+ continue;
+ }
+ }
}
function innerShouldAlsoBeHoisted() {
function hoisting() {
@@ -358,4 +417,9 @@ function moreLabels() {
var $_lcssa;
cheez();
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels"]
+function notComps() {
+ if (!(HEAP32[$incdec_ptr71_i + 8 >> 2] == 0)) {
+ shoo();
+ }
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths", "hoisting", "demangle", "lua", "moreLabels", "notComps"]