aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-06-24 13:50:10 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-06-24 13:50:10 -0700
commite94938b90603372d8dadfbbdc0ed4088ef68078b (patch)
treebc4071d790124cd7c7b3f211401fc7d2d0c81262
parent454e20609b2526c2397cb67386fc759df872fd2f (diff)
relocation pass for shared modules
-rwxr-xr-xtests/runner.py2
-rw-r--r--tools/js-optimizer.js56
-rw-r--r--tools/test-js-optimizer-asm-relocate-output.js9
-rw-r--r--tools/test-js-optimizer-asm-relocate.js12
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 }