diff options
-rw-r--r-- | tools/eliminator/eliminator-test-output.js | 15 | ||||
-rw-r--r-- | tools/eliminator/eliminator-test.js | 6 | ||||
-rw-r--r-- | tools/js-optimizer.js | 50 |
3 files changed, 54 insertions, 17 deletions
diff --git a/tools/eliminator/eliminator-test-output.js b/tools/eliminator/eliminator-test-output.js index bff9071b..00647fca 100644 --- a/tools/eliminator/eliminator-test-output.js +++ b/tools/eliminator/eliminator-test-output.js @@ -105,6 +105,11 @@ function c() { zoom(glob); hail(w2); sunk(y2); + you(fools); + var two = three(); + fools(you); + var noneed2; + noneed2 += fools(you2); return; } function f() { @@ -117,7 +122,7 @@ function g(a1, a2) { foo(c); foo(2); for (var i = 0; i < 5; i++) { - var q = { + { a: 1 } + [ 2, 3 ]; } @@ -131,10 +136,10 @@ function g(a1, a2) { } else { __label__ = 2; } - var sadijn = new asd; + new asd; sadijn2 = "qwe%sert"; this.Module || (this.Module = {}); - var obj = { + { "quoted": 1, "doublequoted": 2, unquoted: 3, @@ -3772,7 +3777,7 @@ function _malloc($bytes) { break; } if ((_sbrk($839) | 0) == -1) { - var $847 = _sbrk($825); + _sbrk($825); var $tsize_0242932_ph_i = $tsize_0_i; break $_$253; } @@ -5399,7 +5404,7 @@ function _mallocNoU($bytes) { break; } if ((_sbrk($839) | 0) == -1) { - var $847 = _sbrk($825); + _sbrk($825); var $tsize_0242932_ph_i = $tsize_0_i; break $_$253; } diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js index d901bc78..e44f28ad 100644 --- a/tools/eliminator/eliminator-test.js +++ b/tools/eliminator/eliminator-test.js @@ -129,6 +129,12 @@ function c() { zoom(z2); hail(w2); sunk(y2); + var fly = you(fools); + var one, two = three(); // more than one var here, so cannot eliminate |two=|, oh well + var noneed; + noneed = fools(you); + var noneed2; + noneed2 += fools(you2); return; } function f() { diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 3cd9788f..6c0a8151 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1417,6 +1417,7 @@ function eliminate(ast, memSafe) { var values = {}; var locals = {}; var varsToRemove = {}; // variables being removed, that we can eliminate all 'var x;' of + var varsToTryToRemove = {}; // variables that have 0 uses, but have side effects - when we scan we can try to remove them // add arguments as locals if (func[2]) { for (var i = 0; i < func[2].length; i++) { @@ -1434,7 +1435,7 @@ function eliminate(ast, memSafe) { if (value) { if (!definitions[name]) definitions[name] = 0; definitions[name]++; - values[name] = value; + if (!values[name]) values[name] = value; } if (!uses[name]) uses[name] = 0; locals[name] = true; @@ -1450,7 +1451,7 @@ function eliminate(ast, memSafe) { if (!definitions[name]) definitions[name] = 0; definitions[name]++; if (!uses[name]) uses[name] = 0; - values[name] = target[2]; + if (!values[name]) values[name] = node[3]; if (node[1] === true) { // not +=, -= etc., just = uses[name]--; // because the name node will show up by itself in the previous case } @@ -1462,21 +1463,27 @@ function eliminate(ast, memSafe) { if (definitions[name] == 1 && uses[name] == 1) { potentials[name] = 1; } else if (uses[name] == 0) { - var mustRemain = false; + var hasSideEffects = false; if (values[name]) { traverse(values[name], function(node, type) { if (!(type in NODES_WITHOUT_ELIMINATION_SIDE_EFFECTS)) { - mustRemain = true; // cannot remove this unused variable, constructing it has side effects + hasSideEffects = true; // cannot remove this unused variable, constructing it has side effects return true; } }); } - if (!mustRemain) varsToRemove[name] = 1; // variable with no uses, might as well remove it + if (!hasSideEffects) { + varsToRemove[name] = 1; // remove it normally + } else { + varsToTryToRemove[name] = 1; // try to remove it later during scanning + } } } //printErr('defs: ' + JSON.stringify(definitions)); //printErr('uses: ' + JSON.stringify(uses)); //printErr('locals: ' + JSON.stringify(locals)); + //printErr('varsToRemove: ' + JSON.stringify(varsToRemove)); + //printErr('2varsToTryToRemove: ' + JSON.stringify(varsToTryToRemove)); definitions = uses = values = null; //printErr('potentials: ' + JSON.stringify(potentials)); // We can now proceed through the function. In each list of statements, we try to eliminate @@ -1593,19 +1600,29 @@ function eliminate(ast, memSafe) { var type = node[0]; if (type == 'assign') { var target = node[2]; + var value = node[3]; var nameTarget = target[0] == 'name'; traverseInOrder(target, true, nameTarget); // evaluate left - traverseInOrder(node[3]); // evaluate right + traverseInOrder(value); // evaluate right // do the actual assignment if (nameTarget) { var name = target[1]; if (!(name in potentials)) { - // expensive check for invalidating specific tracked vars. This list is generally quite short though, because of - // how we just eliminate in short spans and abort when control flow happens TODO: history numbers instead - invalidateByDep(name); // can happen more than once per dep.. - if (!(name in locals) && !globalsInvalidated) { - invalidateGlobals(); - globalsInvalidated = true; + if (!(name in varsToTryToRemove)) { + // expensive check for invalidating specific tracked vars. This list is generally quite short though, because of + // how we just eliminate in short spans and abort when control flow happens TODO: history numbers instead + invalidateByDep(name); // can happen more than once per dep.. + if (!(name in locals) && !globalsInvalidated) { + invalidateGlobals(); + globalsInvalidated = true; + } + } else { + // replace it in-place + node.length = value.length; + for (var i = 0; i < value.length; i++) { + node[i] = value[i]; + } + varsToRemove[name] = 1; } } else { if (allowTracking) track(name, node[3], node); @@ -1638,6 +1655,15 @@ function eliminate(ast, memSafe) { } else { invalidateByDep(name); } + if (vars.length == 1 && name in varsToTryToRemove && value) { + // replace it in-place + value = ['stat', value]; + node.length = value.length; + for (var i = 0; i < value.length; i++) { + node[i] = value[i]; + } + varsToRemove[name] = 1; + } } } } else if (type == 'binary') { |