aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-03-08 12:04:34 -0800
committerAlon Zakai <alonzakai@gmail.com>2013-03-08 12:04:34 -0800
commitca11fd78eb643ab5b28dac2328fb9012dccd1f25 (patch)
tree50b5057a01336eed779e85320108a40ddd3302de /tools
parent49970438a39d7f61d8591aca3f5f2d2d2ada748b (diff)
initial work on asm.js minifier infrastructure
Diffstat (limited to 'tools')
-rw-r--r--tools/js-optimizer.js5
-rw-r--r--tools/js_optimizer.py70
2 files changed, 74 insertions, 1 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 9c744fa3..0387f9fd 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -143,6 +143,8 @@ var FALSE_NODE = ['unary-prefix', '!', ['num', 1]];
var GENERATED_FUNCTIONS_MARKER = '// EMSCRIPTEN_GENERATED_FUNCTIONS';
var generatedFunctions = false; // whether we have received only generated functions
+var minifierInfo = null;
+
function srcToAst(src) {
return uglify.parser.parse(src);
}
@@ -2212,6 +2214,9 @@ var src = read(arguments_[0]);
var ast = srcToAst(src);
//printErr(JSON.stringify(ast)); throw 1;
generatedFunctions = src.indexOf(GENERATED_FUNCTIONS_MARKER) >= 0;
+var minifierInfoStart = src.indexOf('// MINIFY_INFO:')
+if (minifierInfoStart > 0) minifierInfo = JSON.parse(src.substr(minifierInfoStart + 15));
+//printErr(JSON.stringify(minifierInfo));
arguments_.slice(1).forEach(function(arg) {
passes[arg](ast);
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py
index 13e6e4f6..a82dcb9b 100644
--- a/tools/js_optimizer.py
+++ b/tools/js_optimizer.py
@@ -1,5 +1,5 @@
-import os, sys, subprocess, multiprocessing, re
+import os, sys, subprocess, multiprocessing, re, string, json
import shared
configuration = shared.configuration
@@ -19,6 +19,54 @@ WINDOWS = sys.platform.startswith('win')
DEBUG = os.environ.get('EMCC_DEBUG')
+class Minifier:
+ '''
+ asm.js minification support. We calculate possible names and minification of
+ globals here, then pass that into the parallel js-optimizer.js runners which
+ during registerize perform minification of locals.
+ '''
+
+ def __init__(self, globs):
+ # Create list of valid short names
+
+ MAX_NAMES = 200#60000
+ INVALID_2 = set(['do', 'if', 'in'])
+ INVALID_3 = set(['for', 'new', 'try', 'var'])
+
+ 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)
+ #print >> sys.stderr, self.names
+
+ # Minify the globals (initials - asm imports, etc. - and functions)
+ # TODO: find how many times they are used and do this more optimally
+
+ self.globs = {}
+ i = 0
+ for g in globs:
+ self.globs[g] = self.names[i]
+ i += 1
+
+ def serialize(self):
+ return json.dumps({
+ 'names': self.names,
+ 'globals': self.globs
+ })
+
def run_on_chunk(command):
filename = command[2] # XXX hackish
#print >> sys.stderr, 'running js optimizer command', ' '.join(command), '""""', open(filename).read()
@@ -126,12 +174,32 @@ def run_on_js(filename, passes, js_engine, jcache):
else:
cached_outputs = []
+ if 'registerize' in passes:
+ assert suffix, 'need generated info for registerize'
+ # Find basic globals (initial asm.js imports, etc.)
+ asm_marker = pre.find("'use asm'")
+ if asm_marker < 0: asm_marker = pre.find('"use asm"')
+ assert asm_marker > 0
+ asm_funcs = pre.find('function ', asm_marker)
+ assert asm_funcs > asm_marker
+ globs = []
+ for vardef in re.findall(r'var [^;]+;', pre[asm_marker:asm_funcs]):
+ vs = vardef[4:-1].split(',')
+ for v in vs:
+ v = v.split('=')[0].strip()
+ globs.append(v)
+ minify_info = Minifier(globs + list(generated)).serialize()
+ #print >> sys.stderr, 'm', minify_info
+
if len(chunks) > 0:
def write_chunk(chunk, i):
temp_file = temp_files.get('.jsfunc_%d.js' % i).name
f = open(temp_file, 'w')
f.write(chunk)
f.write(suffix_marker)
+ if 'registerize' in passes:
+ f.write('\n')
+ f.write('// MINIFY_INFO:' + minify_info)
f.close()
return temp_file
filenames = [write_chunk(chunks[i], i) for i in range(len(chunks))]