diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-06-24 13:50:10 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-06-24 13:50:10 -0700 |
commit | e94938b90603372d8dadfbbdc0ed4088ef68078b (patch) | |
tree | bc4071d790124cd7c7b3f211401fc7d2d0c81262 | |
parent | 454e20609b2526c2397cb67386fc759df872fd2f (diff) |
relocation pass for shared modules
-rwxr-xr-x | tests/runner.py | 2 | ||||
-rw-r--r-- | tools/js-optimizer.js | 56 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-relocate-output.js | 9 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-relocate.js | 12 |
4 files changed, 79 insertions, 0 deletions
diff --git a/tests/runner.py b/tests/runner.py index 637d2e52..2c459f6f 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -11235,6 +11235,8 @@ f.close() ['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(), ['asm', 'last']), + (path_from_root('tools', 'test-js-optimizer-asm-relocate.js'), open(path_from_root('tools', 'test-js-optimizer-asm-relocate-output.js')).read(), + ['asm', 'relocate']), ]: print input output = Popen(listify(NODE_JS) + [path_from_root('tools', 'js-optimizer.js'), input] + passes, stdin=PIPE, stdout=PIPE).communicate()[0] diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 7f0c97ba..67cd8066 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2713,6 +2713,61 @@ function minifyGlobals(ast) { suffix = '// EXTRA_INFO:' + JSON.stringify(minified); } +// Relocation pass for a shared module (for the functions part of the module) +// +// 1. Replace function names with alternate names as defined (to avoid colliding with +// names in the main module we are being linked to) +// 2. Hardcode function table offsets from F_BASE+x to const+x if x is a variable, or +// the constant sum of the base + offset +// 3. Hardcode heap offsets from H_BASE as well +function relocate(ast) { + assert(asm); // we also assume we are normalized + + var replacements = extraInfo.replacements; + var fBase = extraInfo.fBase; + var hBase = extraInfo.hBase; + + traverse(ast, function(node, type) { + switch(type) { + case 'name': case 'defun': { + var rep = replacements[node[1]]; + if (rep) node[1] = rep; + break; + } + case 'binary': { + if (node[1] == '+' && node[2][0] == 'name') { + var base = null; + if (node[2][1] == 'F_BASE') { + base = fBase; + } else if (node[2][1] == 'H_BASE') { + base = hBase; + } + if (base) { + var other = node[3]; + if (other[0] == 'num') { + other[1] += base; + return other; + } else { + node[2] = ['num', base]; + } + } + } + break; + } + case 'var': { + var vars = node[1]; + for (var i = 0; i < vars.length; i++) { + var name = vars[i][0]; + assert(!(name in replacements)); // cannot shadow functions we are replacing TODO: fix that + } + break; + } + } + }); +} + +// Last pass utilities + // Change +5 to DOT$ZERO(5). We then textually change 5 to 5.0 (uglify's ast cannot differentiate between 5 and 5.0 directly) function prepDotZero(ast) { traverse(ast, function(node, type) { @@ -2777,6 +2832,7 @@ var passes = { eliminate: eliminate, eliminateMemSafe: eliminateMemSafe, minifyGlobals: minifyGlobals, + relocate: relocate, minifyWhitespace: function() { minifyWhitespace = true }, noPrintMetadata: function() { printMetadata = false }, asm: function() { asm = true }, diff --git a/tools/test-js-optimizer-asm-relocate-output.js b/tools/test-js-optimizer-asm-relocate-output.js new file mode 100644 index 00000000..6a197e81 --- /dev/null +++ b/tools/test-js-optimizer-asm-relocate-output.js @@ -0,0 +1,9 @@ +function leaveMeAlone(c) {} +function fixed(a, b) {} +function a(x, y) { + fixed(34, 12); + fixed(34 | 0, 12 | 0); + leaveMeAlone(10 + x, 33 + y); + leaveMeAlone(10 + x | 0, 33 + y | 0); +} + diff --git a/tools/test-js-optimizer-asm-relocate.js b/tools/test-js-optimizer-asm-relocate.js new file mode 100644 index 00000000..a45bc2f0 --- /dev/null +++ b/tools/test-js-optimizer-asm-relocate.js @@ -0,0 +1,12 @@ +function leaveMeAlone(c) { +} +function replaceMe(a, b) { +} +function a(x, y) { + replaceMe(H_BASE + 1, F_BASE + 2); + replaceMe(H_BASE + 1 | 0, F_BASE + 2 | 0); + leaveMeAlone(F_BASE + x, H_BASE + y); + leaveMeAlone(F_BASE + x | 0, H_BASE + y | 0); +} +// EMSCRIPTEN_GENERATED_FUNCTIONS +// EXTRA_INFO: { "replacements": { "replaceMe": "fixed" }, "hBase": 33, "fBase": 10 } |