diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-02-19 18:17:28 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-02-19 18:17:28 -0800 |
commit | 0d6c96a9e5ca386f0f62daf4e95912517fa21893 (patch) | |
tree | 7341d088986fa68480000d88e1799aab443bb14e | |
parent | 379953396230438ab975ca282c40b75f59017be9 (diff) |
collapse elses after the if block breaks or continues, other minor js optimizer fixes
-rw-r--r-- | tools/js-optimizer.js | 57 | ||||
-rw-r--r-- | tools/test-js-optimizer-output.js | 73 | ||||
-rw-r--r-- | tools/test-js-optimizer.js | 66 |
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"] |