diff options
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r-- | tools/js-optimizer.js | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 56ff971c..ce67da89 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1787,6 +1787,7 @@ function eliminate(ast, memSafe) { if (asm) var asmData = normalizeAsm(func); //printErr('eliminate in ' + func[1]); + // First, find the potentially eliminatable functions: that have one definition and one use var definitions = {}; var uses = {}; @@ -1802,6 +1803,7 @@ function eliminate(ast, memSafe) { } } // examine body and note locals + var hasSwitch = false; traverse(func, function(node, type) { if (type === 'var') { var node1 = node[1]; @@ -1833,11 +1835,29 @@ function eliminate(ast, memSafe) { uses[name]--; // because the name node will show up by itself in the previous case } } + } else if (type == 'switch') { + hasSwitch = true; } }); + + // we cannot eliminate variables if there is a switch + if (traverse(func, function(node, type) { + if (type == 'switch') return true; + })) { + if (asm) denormalizeAsm(func, asmData); + return; + } + var potentials = {}; // local variables with 1 definition and 1 use var sideEffectFree = {}; // whether a local variable has no side effects in its definition - for (var name in locals) { + + function unprocessVariable(name) { + if (name in potentials) delete potentials[name]; + if (name in varsToRemove) delete varsToRemove[name]; + if (name in sideEffectFree) delete sideEffectFree[name]; + if (name in varsToTryToRemove) delete varsToTryToRemove[name]; + } + function processVariable(name) { if (definitions[name] == 1 && uses[name] == 1) { potentials[name] = 1; } else if (uses[name] == 0 && (!definitions[name] || definitions[name] <= 1)) { // no uses, no def or 1 def (cannot operate on phis, and the llvm optimizer will remove unneeded phis anyhow) @@ -1862,11 +1882,32 @@ function eliminate(ast, memSafe) { if (!hasSideEffects) { varsToRemove[name] = !definitions[name] ? 2 : 1; // remove it normally sideEffectFree[name] = true; + // Each time we remove a variable with 0 uses, if its value has no + // side effects and vanishes too, then we can remove a use from variables + // appearing in it, and possibly eliminate again + if (value) { + traverse(value, function(node, type) { + if (type == 'name') { + var name = node[1]; + node[1] = ''; // we can remove this - it will never be shown, and should not be left to confuse us as we traverse + if (name in locals) { + uses[name]--; // cannot be infinite recursion since we descend an energy function + assert(uses[name] >= 0); + unprocessVariable(name); + processVariable(name); + } + } + }); + } } else { varsToTryToRemove[name] = 1; // try to remove it later during scanning } } } + for (var name in locals) { + processVariable(name); + } + //printErr('defs: ' + JSON.stringify(definitions)); //printErr('uses: ' + JSON.stringify(uses)); //printErr('values: ' + JSON.stringify(values)); |