aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/js-optimizer.js44
-rw-r--r--tools/js_optimizer.py32
2 files changed, 40 insertions, 36 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index b507a45a..5324e15c 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -1743,6 +1743,36 @@ function getStackBumpSize(ast) {
return node ? node[3][2][3][1] : 0;
}
+// Name minification
+
+var RESERVED = set('do', 'if', 'in', 'for', 'new', 'try', 'var', 'env', 'let');
+var VALID_MIN_INITS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
+var VALID_MIN_LATERS = VALID_MIN_INITS + '0123456789';
+
+var minifiedNames = [];
+var minifiedState = [0];
+
+function ensureMinifiedNames(n) { // make sure the nth index in minifiedNames exists. done 100% deterministically
+ while (minifiedNames.length < n+1) {
+ // generate the current name
+ var name = VALID_MIN_INITS[minifiedState[0]];
+ for (var i = 1; i < minifiedState.length; i++) {
+ name += VALID_MIN_LATERS[minifiedState[i]];
+ }
+ if (!(name in RESERVED)) minifiedNames.push(name);
+ // increment the state
+ var i = 0;
+ while (1) {
+ minifiedState[i]++;
+ if (minifiedState[i] < (i === 0 ? VALID_MIN_INITS : VALID_MIN_LATERS).length) break;
+ // overflow
+ minifiedState[i] = 0;
+ i++;
+ if (i === minifiedState.length) minifiedState.push(-1); // will become 0 after increment in next loop head
+ }
+ }
+}
+
// Very simple 'registerization', coalescing of variables into a smaller number,
// as part of minification. Globals-level minification began in a previous pass,
// we receive extraInfo which tells us how to rename globals. (Only in asm.js.)
@@ -1853,14 +1883,14 @@ function registerize(ast) {
return ret;
}
// find the next free minified name that is not used by a global that shows up in this function
- while (nextRegName < extraInfo.names.length) {
- var ret = extraInfo.names[nextRegName++];
+ while (1) {
+ ensureMinifiedNames(nextRegName);
+ var ret = minifiedNames[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
@@ -2847,16 +2877,16 @@ function minifyGlobals(ast) {
var vars = node[1];
for (var i = 0; i < vars.length; i++) {
var name = vars[i][0];
- assert(next < extraInfo.names.length);
- vars[i][0] = minified[name] = extraInfo.names[next++];
+ ensureMinifiedNames(next);
+ vars[i][0] = minified[name] = minifiedNames[next++];
}
}
});
// add all globals in function chunks, i.e. not here but passed to us
for (var i = 0; i < extraInfo.globals.length; i++) {
name = extraInfo.globals[i];
- assert(next < extraInfo.names.length);
- minified[name] = extraInfo.names[next++];
+ ensureMinifiedNames(next);
+ minified[name] = minifiedNames[next++];
}
// apply minification
traverse(ast, function(node, type) {
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py
index dcc9cd5f..d5b1df27 100644
--- a/tools/js_optimizer.py
+++ b/tools/js_optimizer.py
@@ -24,41 +24,16 @@ import_sig = re.compile('var ([_\w$]+) *=[^;]+;')
class Minifier:
'''
- asm.js minification support. We calculate possible names and minification of
+ asm.js minification support. We calculate minification of
globals here, then pass that into the parallel js-optimizer.js runners which
during registerize perform minification of locals.
'''
- def __init__(self, js, js_engine, MAX_NAMES):
+ def __init__(self, js, js_engine):
self.js = js
self.js_engine = js_engine
- MAX_NAMES = min(MAX_NAMES, 120000)
-
- # Create list of valid short names
-
- INVALID_2 = set(['do', 'if', 'in'])
- INVALID_3 = set(['for', 'new', 'try', 'var', 'env', 'let'])
-
- self.names = []
- init_possibles = string.ascii_letters + '_$'
- later_possibles = init_possibles + string.digits
- for a in init_possibles:
- if len(self.names) >= MAX_NAMES: break
- self.names.append(a)
- for a in init_possibles:
- for b in later_possibles:
- if len(self.names) >= MAX_NAMES: break
- curr = a + b
- if curr not in INVALID_2: self.names.append(curr)
- for a in init_possibles:
- for b in later_possibles:
- for c in later_possibles:
- if len(self.names) >= MAX_NAMES: break
- curr = a + b + c
- if curr not in INVALID_3: self.names.append(curr)
def minify_shell(self, shell, minify_whitespace, source_map=False):
- #print >> sys.stderr, "MINIFY SHELL 1111111111", shell, "\n222222222222222"
# Run through js-optimizer.js to find and minify the global symbols
# We send it the globals, which it parses at the proper time. JS decides how
# to minify all global names, we receive a dictionary back, which is then
@@ -91,7 +66,6 @@ class Minifier:
def serialize(self):
return {
- 'names': self.names,
'globals': self.globs
}
@@ -187,7 +161,7 @@ EMSCRIPTEN_FUNCS();
js = js[start_funcs + len(start_funcs_marker):end_funcs]
# we assume there is a maximum of one new name per line
- minifier = Minifier(js, js_engine, js.count('\n') + asm_shell.count('\n'))
+ minifier = Minifier(js, js_engine)
asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell, 'minifyWhitespace' in passes, source_map).split('EMSCRIPTEN_FUNCS();');
asm_shell_post = asm_shell_post.replace('});', '})');
pre += asm_shell_pre + '\n' + start_funcs_marker