diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-03-08 12:04:34 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-03-08 12:04:34 -0800 |
commit | ca11fd78eb643ab5b28dac2328fb9012dccd1f25 (patch) | |
tree | 50b5057a01336eed779e85320108a40ddd3302de /tools | |
parent | 49970438a39d7f61d8591aca3f5f2d2d2ada748b (diff) |
initial work on asm.js minifier infrastructure
Diffstat (limited to 'tools')
-rw-r--r-- | tools/js-optimizer.js | 5 | ||||
-rw-r--r-- | tools/js_optimizer.py | 70 |
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))] |