diff options
-rwxr-xr-x | tests/runner.py | 2 | ||||
-rw-r--r-- | tools/js-optimizer.js | 65 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-regs-min-output.js | 36 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-regs-min.js | 37 |
4 files changed, 134 insertions, 6 deletions
diff --git a/tests/runner.py b/tests/runner.py index 91de2f74..af12ed80 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -9670,6 +9670,8 @@ f.close() ['asm', 'eliminate']), (path_from_root('tools', 'test-js-optimizer-asm-regs.js'), open(path_from_root('tools', 'test-js-optimizer-asm-regs-output.js')).read(), ['asm', 'registerize']), + (path_from_root('tools', 'test-js-optimizer-asm-regs-min.js'), open(path_from_root('tools', 'test-js-optimizer-asm-regs-min-output.js')).read(), + ['asm', 'registerize']), (path_from_root('tools', 'test-js-optimizer-asm-pre.js'), open(path_from_root('tools', 'test-js-optimizer-asm-pre-output.js')).read(), ['asm', 'simplifyExpressionsPre']), (path_from_root('tools', 'test-js-optimizer-asm-last.js'), open(path_from_root('tools', 'test-js-optimizer-asm-last-output.js')).read(), diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index f944eb9b..5b2e6188 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1445,16 +1445,69 @@ function registerize(ast) { }); vacuum(fun); if (minifierInfo) { - // Fix globals. Note that we know/assume that locals cannot shadow globals. + assert(asm); + var usedGlobals = {}; + var nextLocal = 0; + // Minify globals using the mapping we were given traverse(fun, function(node, type) { if (type == 'name') { - var minified = minifierInfo.globals[node[1]]; - if (minified) node[1] = minified; + var name = node[1]; + var minified = minifierInfo.globals[name]; + if (minified) { + assert(!localVars[name]); // locals must not shadow globals, or else we don't know which is which + if (localVars[minified]) { + // trying to minify a global into a name used locally. rename all the locals + var newName = '$_newLocal_' + (nextLocal++); + assert(!localVars[newName]); + if (params[minified]) { + params[newName] = 1; + delete params[minified]; + } + localVars[newName] = 1; + delete localVars[minified]; + asmData.vars[newName] = asmData.vars[minified]; + delete asmData.vars[minified]; + asmData.params[newName] = asmData.params[minified]; + delete asmData.params[minified]; + traverse(fun, function(node, type) { + if (type == 'name' && node[1] == minified) { + node[1] = newName; + } + }); + if (fun[2]) { + for (var i = 0; i < fun[2].length; i++) { + if (fun[2][i] == minified) fun[2][i] = newName; + } + } + } + node[1] = minified; + usedGlobals[minified] = 1; + } } }); assert(fun[1] in minifierInfo.globals, fun[1]); fun[1] = minifierInfo.globals[fun[1]]; assert(fun[1]); + var nextRegName = 0; + } + var regTypes = {}; + function getNewRegName(num, name) { + if (!asm) return 'r' + num; + var type = asmData.vars[name]; + if (!minifierInfo) { + var ret = (type ? 'd' : 'i') + num; + regTypes[ret] = type; + return ret; + } + // find the next free minified name that is not used by a global that shows up in this function + while (nextRegName < minifierInfo.names.length) { + var ret = minifierInfo.names[nextRegName++]; + if (!usedGlobals[ret]) { + regTypes[ret] = type; + return ret; + } + } + assert('ran out of names'); } // Find the # of uses of each variable. // While doing so, check if all a variable's uses are dominated in a simple @@ -1540,7 +1593,7 @@ function registerize(ast) { saved++; } else { reg = nextReg++; - fullNames[reg] = (asm ? (asmData.vars[name] ? 'd' : 'i') : 'r') + reg; // XXX need to ensure we do not override used globals + fullNames[reg] = getNewRegName(reg, name); if (params[name]) paramRegs[reg] = 1; } varRegs[name] = reg; @@ -1584,7 +1637,7 @@ function registerize(ast) { if (loopRegs[loops]) { if (asm) { loopRegs[loops].forEach(function(loopReg) { - freeRegsClasses[fullNames[loopReg][0] == 'i' ? ASM_INT : ASM_DOUBLE].push(loopReg); + freeRegsClasses[regTypes[fullNames[loopReg]]].push(loopReg); }); } else { freeRegsClasses = freeRegsClasses.concat(loopRegs[loops]); @@ -1620,7 +1673,7 @@ function registerize(ast) { }; for (var i = 1; i < nextReg; i++) { var reg = fullNames[i]; - var type = reg[0] == 'i' ? ASM_INT : ASM_DOUBLE + var type = regTypes[reg]; if (!paramRegs[i]) { finalAsmData.vars[reg] = type; } else { diff --git a/tools/test-js-optimizer-asm-regs-min-output.js b/tools/test-js-optimizer-asm-regs-min-output.js new file mode 100644 index 00000000..b8088022 --- /dev/null +++ b/tools/test-js-optimizer-asm-regs-min-output.js @@ -0,0 +1,36 @@ +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} +function cl(b) { + b = b | 0; + var c = 0; + c = b * b; + a(c); + i1(b); +} + diff --git a/tools/test-js-optimizer-asm-regs-min.js b/tools/test-js-optimizer-asm-regs-min.js new file mode 100644 index 00000000..c126946d --- /dev/null +++ b/tools/test-js-optimizer-asm-regs-min.js @@ -0,0 +1,37 @@ +function collideLocal(x) { + x = x | 0; + var a = 0; + a = x*x; + aGlobal(a); // aGlobal needs to be minified into a, but a is used! + bGlobal(x); +} +function collideLocal(x) { + x = x | 0; + var i1 = 0; + i1 = x*x; + aGlobal(i1); + bGlobal(x); // bGlobal needs to be minified into i1, but i1 is used! +} +function collideLocal(a) { + a = a | 0; + var x = 0; + x = a*a; + aGlobal(x); // aGlobal needs to be minified into a, but a is used by a param! + bGlobal(a); +} +function collideLocal(i1) { + i1 = i1 | 0; + var x = 0; + x = i1*i1; + aGlobal(x); + bGlobal(i1); // bGlobal needs to be minified into i1, but i1 is used by a param! +} +function collideLocal(i1) { + i1 = i1 | 0; + var a = 0; + a = i1*i1; + aGlobal(a); // multiple collisions, a and i1 + bGlobal(i1); +} +// EMSCRIPTEN_GENERATED_FUNCTIONS +// MINIFY_INFO: { "names": ["a", "b", "c", "d", "e", "f", "g", "h", "i", "i1", "cl"], "globals": { "aGlobal": "a", "bGlobal": "i1", "collideLocal": "cl" } } |