diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-11-09 09:55:18 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-11-09 09:55:18 -0800 |
commit | d420405180ee7910511c6a89572ce9f823880f3a (patch) | |
tree | f25b3ae56eafe4085329185e81ee891db73997fe | |
parent | 16a5d12dc19b984cf3b55fc2682bd24f1d6834c4 (diff) |
Math.* have no side effects
-rw-r--r-- | tools/eliminator/eliminator-test-output.js | 3 | ||||
-rw-r--r-- | tools/eliminator/eliminator-test.js | 10 | ||||
-rw-r--r-- | tools/js-optimizer.js | 32 |
3 files changed, 36 insertions, 9 deletions
diff --git a/tools/eliminator/eliminator-test-output.js b/tools/eliminator/eliminator-test-output.js index 1a6506ed..0171e99b 100644 --- a/tools/eliminator/eliminator-test-output.js +++ b/tools/eliminator/eliminator-test-output.js @@ -6119,4 +6119,7 @@ function intoCond() { HEAP32[$115 >> 2] = $NumWords; } } +function math(a, b, c, d) { + print(Math_imul(d) + (Math_fround(c) + (a + Math_abs(b)))); +} diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js index ffad69ea..ef17b388 100644 --- a/tools/eliminator/eliminator-test.js +++ b/tools/eliminator/eliminator-test.js @@ -8852,5 +8852,13 @@ function intoCond() { HEAP32[$504 >> 2] = $503; } } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi", "intoCond"] +function math(a, b, c, d) { + var x, y, z, w; + x = a; + y = Math_abs(b); + z = Math_fround(c); + w = Math_imul(d); + print(x + y + z + w); +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi", "intoCond", "math"] diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 8b05fc38..d2bfcd91 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1142,12 +1142,26 @@ function simplifyNotComps(ast) { simplifyNotCompsPass = false; } +function callHasSideEffects(node) { // checks if the call itself (not the args) has side effects (or is not statically known) + return !(node[1][0] === 'name' && /^Math_/.test(node[1][1])); +} + function hasSideEffects(node) { // this is 99% incomplete! switch (node[0]) { case 'num': case 'name': case 'string': return false; case 'unary-prefix': return hasSideEffects(node[2]); case 'binary': return hasSideEffects(node[2]) || hasSideEffects(node[3]); case 'sub': return hasSideEffects(node[1]) || hasSideEffects(node[2]); + case 'call': { + if (callHasSideEffects(node)) return true; + // This is a statically known call, with no side effects. only args can side effect us + var args = node[2]; + var num = args.length; + for (var i = 0; i < num; i++) { + if (hasSideEffects(args[i])) return true; + } + return false; + } default: return true; } } @@ -2445,14 +2459,16 @@ function eliminate(ast, memSafe) { for (var i = 0; i < args.length; i++) { traverseInOrder(args[i]); } - // these two invalidations will also invalidate calls - if (!globalsInvalidated) { - invalidateGlobals(); - globalsInvalidated = true; - } - if (!memoryInvalidated) { - invalidateMemory(); - memoryInvalidated = true; + if (callHasSideEffects(node)) { + // these two invalidations will also invalidate calls + if (!globalsInvalidated) { + invalidateGlobals(); + globalsInvalidated = true; + } + if (!memoryInvalidated) { + invalidateMemory(); + memoryInvalidated = true; + } } } else if (type === 'if') { if (allowTracking) { |