diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-06-07 10:02:56 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-06-07 10:09:12 -0700 |
commit | 523ed62b3c68ef4dc04fb2918ae8b1b2f8e2bce1 (patch) | |
tree | f57f2e9f26b67009c1b172a96d528085fd5f13cd /tools/js-optimizer.js | |
parent | 265dd5a4e28ebd280dafb5febca1b556abc473e8 (diff) |
optimize multiple loop variables together
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r-- | tools/js-optimizer.js | 103 |
1 files changed, 59 insertions, 44 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 2b05aeb3..8e815100 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2374,57 +2374,72 @@ function eliminate(ast, memSafe) { ifTrue = temp; flip = true; } - if (ifTrue[1][0][0] == 'break' && !ifTrue[1][1] && ifFalse[1].length == 1 && ifFalse[1][0][0] == 'stat' && ifFalse[1][0][1][0] == 'assign') { - var assign = ifFalse[1][0][1]; - if (assign[1] === true && assign[2][0] == 'name' && assign[3][0] == 'name') { - var looper = assign[2][1]; - var helper = assign[3][1]; - if (definitions[helper] == 1 && seenUses[looper] == namings[looper] && - !helperReplacements[helper] && !helperReplacements[looper]) { - // the remaining issue is whether looper is used after the assignment to helper and before the last line (where we assign to it) - var found = -1; - for (var i = stats.length-2; i >= 0; i--) { - var curr = stats[i]; - if (curr[0] == 'stat' && curr[1][0] == 'assign') { - var currAssign = curr[1]; - if (currAssign[1] === true && currAssign[2][0] == 'name') { - var to = currAssign[2][1]; - if (to == helper) { - found = i; - break; - } - } + if (ifTrue[1][0][0] == 'break' && !ifTrue[1][1]) { + var assigns = ifFalse[1]; + var loopers = [], helpers = []; + for (var i = 0; i < assigns.length; i++) { + if (assigns[i][0] == 'stat' && assigns[i][1][0] == 'assign') { + var assign = assigns[i][1]; + if (assign[1] === true && assign[2][0] == 'name' && assign[3][0] == 'name') { + var looper = assign[2][1]; + var helper = assign[3][1]; + if (definitions[helper] == 1 && seenUses[looper] == namings[looper] && + !helperReplacements[helper] && !helperReplacements[looper]) { + loopers.push(looper); + helpers.push(helper); } } - if (found >= 0) { - var looperUsed = false; - for (var i = found+1; i < stats.length && !looperUsed; i++) { - var curr = i < stats.length-1 ? stats[i] : last[1]; // on the last line, just look in the condition - traverse(curr, function(node, type) { - if (type == 'name' && node[1] == looper) { - looperUsed = true; - return true; - } - }); - } - if (!looperUsed) { - // hurrah! this is safe to do - varsToRemove[helper] = 2; - traverse(node, function(node, type) { // replace all appearances of helper with looper - if (type == 'name' && node[1] == helper) node[1] = looper; - }); - helperReplacements[helper] = looper; // replace all future appearances of helper with looper - helperReplacements[looper] = looper; // avoid any further attempts to optimize looper in this manner (seenUses is wrong anyhow, too) - // simplify the if. we remove the if branch, leaving only the else - if (flip) { - last[1] = simplifyNotComps(['unary-prefix', '!', last[1]]); - last[2] = last[3]; + } + } + if (loopers.length < assigns.length) return; // TODO: handle the case where can can just eliminate one. (we can't optimize the break, but we can remove the var at least) + for (var l = 0; l < loopers.length; l++) { + var looper = loopers[l]; + var helper = helpers[l]; + // the remaining issue is whether loopers are used after the assignment to helper and before the last line (where we assign to it) + var found = -1; + for (var i = stats.length-2; i >= 0; i--) { + var curr = stats[i]; + if (curr[0] == 'stat' && curr[1][0] == 'assign') { + var currAssign = curr[1]; + if (currAssign[1] === true && currAssign[2][0] == 'name') { + var to = currAssign[2][1]; + if (to == helper) { + found = i; + break; } - last.pop(); } } } + if (found < 0) return; + var looperUsed = false; + for (var i = found+1; i < stats.length && !looperUsed; i++) { + var curr = i < stats.length-1 ? stats[i] : last[1]; // on the last line, just look in the condition + traverse(curr, function(node, type) { + if (type == 'name' && node[1] == looper) { + looperUsed = true; + return true; + } + }); + } + if (looperUsed) return; + } + // hurrah! this is safe to do + for (var l = 0; l < loopers.length; l++) { + var looper = loopers[l]; + var helper = helpers[l]; + varsToRemove[helper] = 2; + traverse(node, function(node, type) { // replace all appearances of helper with looper + if (type == 'name' && node[1] == helper) node[1] = looper; + }); + helperReplacements[helper] = looper; // replace all future appearances of helper with looper + helperReplacements[looper] = looper; // avoid any further attempts to optimize looper in this manner (seenUses is wrong anyhow, too) + } + // simplify the if. we remove the if branch, leaving only the else + if (flip) { + last[1] = simplifyNotComps(['unary-prefix', '!', last[1]]); + last[2] = last[3]; } + last.pop(); } } } |