From 82ddb0715d1aa655841223cff314a5377fe10aa5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 10:17:44 -0800 Subject: send only a marker of generated functions to js-optimizer.js; we either know the generated functions and send only them, or we don't know them and send all the code, in either case js-optimizer.js does not need a list of generated functions --- tools/js_optimizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 2fd2211b..13e6e4f6 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -131,7 +131,7 @@ def run_on_js(filename, passes, js_engine, jcache): temp_file = temp_files.get('.jsfunc_%d.js' % i).name f = open(temp_file, 'w') f.write(chunk) - f.write(suffix) + f.write(suffix_marker) f.close() return temp_file filenames = [write_chunk(chunks[i], i) for i in range(len(chunks))] -- cgit v1.2.3-70-g09d2 From ca11fd78eb643ab5b28dac2328fb9012dccd1f25 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 12:04:34 -0800 Subject: initial work on asm.js minifier infrastructure --- tools/js-optimizer.js | 5 ++++ tools/js_optimizer.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) (limited to 'tools/js_optimizer.py') 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))] -- cgit v1.2.3-70-g09d2 From 52b9d04de89f922d9499415f2fe04f8ff6375e9f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 12:23:18 -0800 Subject: fix global minifying --- tools/js_optimizer.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index a82dcb9b..b7d342d2 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -26,12 +26,12 @@ class Minifier: during registerize perform minification of locals. ''' - def __init__(self, globs): + def __init__(self): # Create list of valid short names MAX_NAMES = 200#60000 INVALID_2 = set(['do', 'if', 'in']) - INVALID_3 = set(['for', 'new', 'try', 'var']) + INVALID_3 = set(['for', 'new', 'try', 'var', 'env']) self.names = [] init_possibles = string.ascii_letters + '_$' @@ -52,14 +52,14 @@ class Minifier: if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names + self.globs = {} + + def add_glob(self, glob): # 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 + ret = self.names[len(self.globs)] + self.globs[glob] = ret + return ret def serialize(self): return json.dumps({ @@ -182,14 +182,19 @@ def run_on_js(filename, passes, js_engine, jcache): assert asm_marker > 0 asm_funcs = pre.find('function ', asm_marker) assert asm_funcs > asm_marker - globs = [] + minifier = Minifier() + new_vars = '' 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 + name, value = map(lambda x: x.strip(), v.split('=')) + new_vars += 'var ' + minifier.add_glob(name) + '=' + value + ';' + for g in generated: + minifier.add_glob(g) + minify_info = minifier.serialize() + minifier = None + pre = pre[:asm_marker+11] + new_vars + pre[asm_funcs:] + print >> sys.stderr, 'm', minify_info if len(chunks) > 0: def write_chunk(chunk, i): -- cgit v1.2.3-70-g09d2 From bdaddc1e00ff169ee7491d84e318e4a159c71013 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 14:24:04 -0800 Subject: disable minification --- tools/js_optimizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index b7d342d2..9e12ef2d 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -174,7 +174,7 @@ def run_on_js(filename, passes, js_engine, jcache): else: cached_outputs = [] - if 'registerize' in passes: + if 'zzzregisterize' in passes: assert suffix, 'need generated info for registerize' # Find basic globals (initial asm.js imports, etc.) asm_marker = pre.find("'use asm'") @@ -202,7 +202,7 @@ def run_on_js(filename, passes, js_engine, jcache): f = open(temp_file, 'w') f.write(chunk) f.write(suffix_marker) - if 'registerize' in passes: + if 'zzzregisterize' in passes: f.write('\n') f.write('// MINIFY_INFO:' + minify_info) f.close() -- cgit v1.2.3-70-g09d2 From 21804c07c76ac3e0be86b2db6ba1c456ab0bae28 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 15:29:39 -0800 Subject: add explicit markers in generated code of where functions and asm are --- emscripten.py | 20 +++++++++++++++----- tools/js_optimizer.py | 44 ++++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 27 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/emscripten.py b/emscripten.py index b698654b..2291a65a 100755 --- a/emscripten.py +++ b/emscripten.py @@ -332,9 +332,9 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, params = ','.join(['p%d' % p for p in range(len(sig)-1)]) coercions = ';'.join(['p%d = %sp%d%s' % (p, '+' if sig[p+1] != 'i' else '', p, '' if sig[p+1] != 'i' else '|0') for p in range(len(sig)-1)]) + ';' ret = '' if sig[0] == 'v' else ('return %s0' % ('+' if sig[0] != 'i' else '')) - return ('function %s(%s) { %s abort(%d); %s };' % (bad, params, coercions, i, ret), raw.replace('[0,', '[' + bad + ',').replace(',0,', ',' + bad + ',').replace(',0,', ',' + bad + ',').replace(',0]', ',' + bad + ']').replace(',0]', ',' + bad + ']').replace(',0\n', ',' + bad + '\n')) + return ('function %s(%s) { %s abort(%d); %s }' % (bad, params, coercions, i, ret), raw.replace('[0,', '[' + bad + ',').replace(',0,', ',' + bad + ',').replace(',0,', ',' + bad + ',').replace(',0]', ',' + bad + ']').replace(',0]', ',' + bad + ']').replace(',0\n', ',' + bad + '\n')) infos = [make_table(sig, raw) for sig, raw in last_forwarded_json['Functions']['tables'].iteritems()] - function_tables_defs = '\n'.join([info[0] for info in infos] + [info[1] for info in infos]) + function_tables_defs = '\n'.join([info[0] for info in infos]) + '\n// EMSCRIPTEN_END_FUNCS\n' + '\n'.join([info[1] for info in infos]) asm_setup = '' maths = ['Math.' + func for func in ['floor', 'abs', 'sqrt', 'pow', 'cos', 'sin', 'tan', 'acos', 'asin', 'atan', 'atan2', 'exp', 'log', 'ceil', 'imul']] @@ -416,6 +416,7 @@ function asmPrintInt(x, y) { function asmPrintFloat(x, y) { Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); } +// EMSCRIPTEN_START_ASM var asm = (function(global, env, buffer) { 'use asm'; var HEAP8 = new global.Int8Array(buffer); @@ -456,12 +457,15 @@ var asm = (function(global, env, buffer) { value = value|0; tempRet%d = value; } -''' % (i, i) for i in range(10)]) + funcs_js + ''' - +''' % (i, i) for i in range(10)]) + ''' +// EMSCRIPTEN_START_FUNCS +''' + funcs_js + ''' %s return %s; -})(%s, %s, buffer); +}) +// EMSCRIPTEN_END_ASM +(%s, %s, buffer); %s; Runtime.stackAlloc = function(size) { return asm.stackAlloc(size) }; Runtime.stackSave = function() { return asm.stackSave() }; @@ -483,6 +487,12 @@ Runtime.stackRestore = function(top) { asm.stackRestore(top) }; else: function_tables_defs = '\n'.join([table for table in last_forwarded_json['Functions']['tables'].itervalues()]) outfile.write(function_tables_defs) + funcs_js = ''' +// EMSCRIPTEN_START_FUNCS +''' + funcs_js + ''' +// EMSCRIPTEN_END_FUNCS +''' + outfile.write(blockaddrsize(indexize(funcs_js))) funcs_js = None diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 9e12ef2d..5c155ff5 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -98,6 +98,19 @@ def run_on_js(filename, passes, js_engine, jcache): # if there is metadata, we will run only on the generated functions. If there isn't, we will run on everything. generated = set(eval(suffix[len(suffix_marker)+1:])) + # Find markers + start_funcs_marker = '// EMSCRIPTEN_START_FUNCS\n' + end_funcs_marker = '// EMSCRIPTEN_END_FUNCS\n' + start_funcs = js.find(start_funcs_marker) + end_funcs = js.find(end_funcs_marker) + assert (start_funcs >= 0) == (end_funcs >= 0) == (not not suffix) + if 'asm' in passes: + start_asm_marker = '// EMSCRIPTEN_START_ASM\n' + end_asm_marker = '// EMSCRIPTEN_END_ASM\n' + start_asm = js.find(start_asm_marker) + end_asm = js.find(end_asm_marker) + assert (start_asm >= 0) == (end_asm >= 0) + if not suffix and jcache: # JCache cannot be used without metadata, since it might reorder stuff, and that's dangerous since only generated can be reordered # This means jcache does not work after closure compiler runs, for example. But you won't get much benefit from jcache with closure @@ -105,37 +118,24 @@ def run_on_js(filename, passes, js_engine, jcache): if DEBUG: print >>sys.stderr, 'js optimizer: no metadata, so disabling jcache' jcache = False - # If we process only generated code, find that and save the rest on the side - func_sig = re.compile('( *)function (_[\w$]+)\(') if suffix: - pos = 0 - gen_start = 0 - gen_end = 0 - while 1: - m = func_sig.search(js, pos) - if not m: break - pos = m.end() - indent = m.group(1) - ident = m.group(2) - if ident in generated: - if not gen_start: - gen_start = m.start() - assert gen_start - gen_end = js.find('\n%s}\n' % indent, m.end()) + (3 + len(indent)) - assert gen_end > gen_start - pre = js[:gen_start] - post = js[gen_end:] - if 'last' in passes: - post = post.replace(suffix, '') # no need to write out the metadata - nothing after us needs it - js = js[gen_start:gen_end] + pre = js[:start_funcs + len(start_funcs_marker)] + post = js[end_funcs:] + js = js[start_funcs + len(start_funcs_marker):end_funcs] + if 'asm' not in passes: # can have Module[..] and inlining prevention code, push those to post + for line in js.split('\n'): + if len(line) > 0 and not line.startswith((' ', 'function', '}')): + post = line + '\n' + post else: pre = '' post = '' + generated # Pick where to split into chunks, so that (1) they do not oom in node/uglify, and (2) we can run them in parallel # If we have metadata, we split only the generated code, and save the pre and post on the side (and do not optimize them) parts = map(lambda part: part, js.split('\n}\n')) funcs = [] + func_sig = re.compile('( *)function ([_\w$]+)\(') for i in range(len(parts)): func = parts[i] if i < len(parts)-1: func += '\n}\n' # last part needs no } -- cgit v1.2.3-70-g09d2 From 50c7f9f00e4666860bf1f39181cc6f9133ef46bb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 15:58:28 -0800 Subject: remove unneeded line --- tools/js_optimizer.py | 1 - 1 file changed, 1 deletion(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 5c155ff5..a7d9c1e1 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -129,7 +129,6 @@ def run_on_js(filename, passes, js_engine, jcache): else: pre = '' post = '' - generated # Pick where to split into chunks, so that (1) they do not oom in node/uglify, and (2) we can run them in parallel # If we have metadata, we split only the generated code, and save the pre and post on the side (and do not optimize them) -- cgit v1.2.3-70-g09d2 From b31addd3ab55af8dddb703580ebf5d2a90660c61 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 16:17:52 -0800 Subject: split out asm shell in js optimizer, in preparation for minification of globals --- emscripten.py | 5 ++--- tools/js_optimizer.py | 34 ++++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/emscripten.py b/emscripten.py index 2291a65a..09a57e37 100755 --- a/emscripten.py +++ b/emscripten.py @@ -433,6 +433,7 @@ var asm = (function(global, env, buffer) { var tempInt = 0, tempBigInt = 0, tempBigIntP = 0, tempBigIntS = 0, tempBigIntR = 0.0, tempBigIntI = 0, tempBigIntD = 0, tempValue = 0, tempDouble = 0.0; ''' + ''.join([''' var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs + ''' +// EMSCRIPTEN_START_FUNCS function stackAlloc(size) { size = size|0; var ret = 0; @@ -457,9 +458,7 @@ var asm = (function(global, env, buffer) { value = value|0; tempRet%d = value; } -''' % (i, i) for i in range(10)]) + ''' -// EMSCRIPTEN_START_FUNCS -''' + funcs_js + ''' +''' % (i, i) for i in range(10)]) + funcs_js + ''' %s return %s; diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index a7d9c1e1..4661580b 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -102,13 +102,14 @@ def run_on_js(filename, passes, js_engine, jcache): start_funcs_marker = '// EMSCRIPTEN_START_FUNCS\n' end_funcs_marker = '// EMSCRIPTEN_END_FUNCS\n' start_funcs = js.find(start_funcs_marker) - end_funcs = js.find(end_funcs_marker) + end_funcs = js.rfind(end_funcs_marker) assert (start_funcs >= 0) == (end_funcs >= 0) == (not not suffix) - if 'asm' in passes: + asm_registerize = 'asm' in passes and 'registerize' in passes + if asm_registerize: start_asm_marker = '// EMSCRIPTEN_START_ASM\n' end_asm_marker = '// EMSCRIPTEN_END_ASM\n' start_asm = js.find(start_asm_marker) - end_asm = js.find(end_asm_marker) + end_asm = js.rfind(end_asm_marker) assert (start_asm >= 0) == (end_asm >= 0) if not suffix and jcache: @@ -119,13 +120,26 @@ def run_on_js(filename, passes, js_engine, jcache): jcache = False if suffix: - pre = js[:start_funcs + len(start_funcs_marker)] - post = js[end_funcs:] - js = js[start_funcs + len(start_funcs_marker):end_funcs] - if 'asm' not in passes: # can have Module[..] and inlining prevention code, push those to post - for line in js.split('\n'): - if len(line) > 0 and not line.startswith((' ', 'function', '}')): - post = line + '\n' + post + if not asm_registerize: + pre = js[:start_funcs + len(start_funcs_marker)] + post = js[end_funcs:] + js = js[start_funcs + len(start_funcs_marker):end_funcs] + if 'asm' not in passes: # can have Module[..] and inlining prevention code, push those to post + for line in js.split('\n'): + if len(line) > 0 and not line.startswith((' ', 'function', '}')): + post = line + '\n' + post + else: + # We need to split out the asm shell as well, for minification + pre = js[:start_asm + len(start_asm_marker)] + post = js[end_asm:] + asm_shell = js[start_asm + len(start_asm_marker):start_funcs + len(start_funcs_marker)] + ''' +EMSCRIPTEN_FUNCS(); +''' + js[end_funcs + len(end_funcs_marker):end_asm + len(end_asm_marker)] + minified_asm_shell = asm_shell # TODO: minification of globals + asm_shell_pre, asm_shell_post = minified_asm_shell.split('EMSCRIPTEN_FUNCS();'); + pre += asm_shell_pre + post = asm_shell_post + post + js = js[start_funcs + len(start_funcs_marker):end_funcs] else: pre = '' post = '' -- cgit v1.2.3-70-g09d2 From dac020142d05493a1c47632e561f4069a85ee13a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 17:12:22 -0800 Subject: minify globals in a pass before the functions --- tools/js-optimizer.js | 35 +++++++++++++++++++++++++++++++++++ tools/js_optimizer.py | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 69 insertions(+), 11 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 77ad0ba3..092c9f35 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2159,6 +2159,37 @@ function eliminateMemSafe(ast) { eliminate(ast, true); } +function minifyGlobals(ast) { + var minified = {}; + var next = 0; + var first = true; // do not minify initial 'var asm =' + traverse(ast, function(node, type) { + if (type == 'var') { + if (first) { + first = false; + return; + } + var vars = node[1]; + for (var i = 0; i < vars.length; i++) { + var name = vars[i][0]; + vars[i][0] = minified[name] = minifierInfo.names[next++]; + } + } else if (type == 'name') { + var name = node[1]; + if (name in minified) { + node[1] = minified[name]; + } else if (name == 'EMSCRIPTEN_FUNCS') { + // minify all the globals + for (var i = 0; i < minifierInfo.globals.length; i++) { + name = minifierInfo.globals[i]; + minified[name] = minifierInfo.names[next++]; + } + } + } + }); + suffix = '// MINIFY_INFO:' + JSON.stringify(minified); +} + // 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) { @@ -2204,6 +2235,7 @@ var passes = { registerize: registerize, eliminate: eliminate, eliminateMemSafe: eliminateMemSafe, + minifyGlobals: minifyGlobals, compress: function() { compress = true }, noPrintMetadata: function() { printMetadata = false }, asm: function() { asm = true }, @@ -2212,6 +2244,8 @@ var passes = { // Main +var suffix = ''; + var src = read(arguments_[0]); var ast = srcToAst(src); //printErr(JSON.stringify(ast)); throw 1; @@ -2238,4 +2272,5 @@ do { } while (js != old); print(js); print('\n'); +print(suffix); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 4661580b..cc7e8104 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -19,6 +19,8 @@ WINDOWS = sys.platform.startswith('win') DEBUG = os.environ.get('EMCC_DEBUG') +func_sig = re.compile('( *)function ([_\w$]+)\(') + class Minifier: ''' asm.js minification support. We calculate possible names and minification of @@ -26,7 +28,10 @@ class Minifier: during registerize perform minification of locals. ''' - def __init__(self): + def __init__(self, js, js_engine): + self.js = js + self.js_engine = js_engine + # Create list of valid short names MAX_NAMES = 200#60000 @@ -52,14 +57,30 @@ class Minifier: if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names - self.globs = {} + def minify_shell(self, shell): + #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 + # used by the function processors + + # Find all globals in the JS functions code + self.globs = [m.group(2) for m in func_sig.finditer(self.js)] + + temp_file = temp_files.get('.minifyglobals.js').name + f = open(temp_file, 'w') + f.write(shell) + f.write('\n') + self + f.write('// MINIFY_INFO:' + self.serialize()) + f.close() - def add_glob(self, glob): - # Minify the globals (initials - asm imports, etc. - and functions) - # TODO: find how many times they are used and do this more optimally - ret = self.names[len(self.globs)] - self.globs[glob] = ret - return ret + output = subprocess.Popen(self.js_engine + [JS_OPTIMIZER, temp_file, 'minifyGlobals', 'noPrintMetadata'], stdout=subprocess.PIPE).communicate()[0] + assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + output + #print >> sys.stderr, "minified SHELL 3333333333333333", output, "\n44444444444444444444" + code, metadata = output.split('// MINIFY_INFO:') + self.globs = json.loads(metadata) + return output def serialize(self): return json.dumps({ @@ -135,11 +156,14 @@ def run_on_js(filename, passes, js_engine, jcache): asm_shell = js[start_asm + len(start_asm_marker):start_funcs + len(start_funcs_marker)] + ''' EMSCRIPTEN_FUNCS(); ''' + js[end_funcs + len(end_funcs_marker):end_asm + len(end_asm_marker)] - minified_asm_shell = asm_shell # TODO: minification of globals + js = js[start_funcs + len(start_funcs_marker):end_funcs] + + minifier = Minifier(js, js_engine) + minified_asm_shell = minifier.minify_shell(asm_shell) + asm_shell_pre, asm_shell_post = minified_asm_shell.split('EMSCRIPTEN_FUNCS();'); pre += asm_shell_pre post = asm_shell_post + post - js = js[start_funcs + len(start_funcs_marker):end_funcs] else: pre = '' post = '' @@ -148,7 +172,6 @@ EMSCRIPTEN_FUNCS(); # If we have metadata, we split only the generated code, and save the pre and post on the side (and do not optimize them) parts = map(lambda part: part, js.split('\n}\n')) funcs = [] - func_sig = re.compile('( *)function ([_\w$]+)\(') for i in range(len(parts)): func = parts[i] if i < len(parts)-1: func += '\n}\n' # last part needs no } -- cgit v1.2.3-70-g09d2 From 8a7a96a56bcb63d19c03c0c93c662c9493c3c77f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 17:30:58 -0800 Subject: start to minify inside functions, using global data from previous pass --- tools/js-optimizer.js | 14 +++++++++++++- tools/js_optimizer.py | 30 ++++-------------------------- 2 files changed, 17 insertions(+), 27 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 092c9f35..7b774dee 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1397,14 +1397,26 @@ function denormalizeAsm(func, data) { //printErr('denormalized \n\n' + astToSrc(func) + '\n\n'); } -// Very simple 'registerization', coalescing of variables into a smaller number. +// Very simple 'registerization', coalescing of variables into a smaller number, +// as part of minification. Globals-level minification began in a previous pass, +// we receive minifierInfo which tells us how to rename globals. +// // We do not optimize when there are switches, so this pass only makes sense with // relooping. // TODO: Consider how this fits in with the rest of the optimization toolchain. Do // we still need the eliminator? Closure? And in what order? Perhaps just // closure simple? function registerize(ast) { + assert(minifierInfo); + traverseGeneratedFunctions(ast, function(fun) { + // First, fix globals. Note that we know/assume that locals cannot shadow globals. + traverse(fun, function(node, type) { + if (type == 'name') { + var minified = minifierInfo.globals[node[1]]; + if (minified) node[1] = minified; + } + }); if (asm) var asmData = normalizeAsm(fun); // Add parameters as a first (fake) var (with assignment), so they get taken into consideration var params = {}; // note: params are special, they can never share a register between them (see later) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index cc7e8104..b5213ac3 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -159,11 +159,11 @@ EMSCRIPTEN_FUNCS(); js = js[start_funcs + len(start_funcs_marker):end_funcs] minifier = Minifier(js, js_engine) - minified_asm_shell = minifier.minify_shell(asm_shell) - - asm_shell_pre, asm_shell_post = minified_asm_shell.split('EMSCRIPTEN_FUNCS();'); + asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell).split('EMSCRIPTEN_FUNCS();'); pre += asm_shell_pre post = asm_shell_post + post + + minify_info = minifier.serialize() else: pre = '' post = '' @@ -210,35 +210,13 @@ EMSCRIPTEN_FUNCS(); else: cached_outputs = [] - if 'zzzregisterize' 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 - minifier = Minifier() - new_vars = '' - for vardef in re.findall(r'var [^;]+;', pre[asm_marker:asm_funcs]): - vs = vardef[4:-1].split(',') - for v in vs: - name, value = map(lambda x: x.strip(), v.split('=')) - new_vars += 'var ' + minifier.add_glob(name) + '=' + value + ';' - for g in generated: - minifier.add_glob(g) - minify_info = minifier.serialize() - minifier = None - pre = pre[:asm_marker+11] + new_vars + pre[asm_funcs:] - 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 'zzzregisterize' in passes: + if asm_registerize: f.write('\n') f.write('// MINIFY_INFO:' + minify_info) f.close() -- cgit v1.2.3-70-g09d2 From c65bba4e0d06db216c1176c4b02f98d816a9cfd7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 17:45:58 -0800 Subject: remove unnecessary semicolon; hello world minifies --- tools/js_optimizer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index b5213ac3..afbf1cc7 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -80,7 +80,7 @@ class Minifier: #print >> sys.stderr, "minified SHELL 3333333333333333", output, "\n44444444444444444444" code, metadata = output.split('// MINIFY_INFO:') self.globs = json.loads(metadata) - return output + return code def serialize(self): return json.dumps({ @@ -160,6 +160,7 @@ EMSCRIPTEN_FUNCS(); minifier = Minifier(js, js_engine) asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell).split('EMSCRIPTEN_FUNCS();'); + asm_shell_post = asm_shell_post.replace('});', '})'); pre += asm_shell_pre post = asm_shell_post + post -- cgit v1.2.3-70-g09d2 From 0764a9d32f80ae30ad824dcdc20b174653d2b185 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:15:07 -0800 Subject: increase number of minified names, and add func markers --- tools/js_optimizer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index afbf1cc7..bac693bf 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -34,7 +34,7 @@ class Minifier: # Create list of valid short names - MAX_NAMES = 200#60000 + MAX_NAMES = 6000#0 INVALID_2 = set(['do', 'if', 'in']) INVALID_3 = set(['for', 'new', 'try', 'var', 'env']) @@ -161,8 +161,8 @@ EMSCRIPTEN_FUNCS(); minifier = Minifier(js, js_engine) asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell).split('EMSCRIPTEN_FUNCS();'); asm_shell_post = asm_shell_post.replace('});', '})'); - pre += asm_shell_pre - post = asm_shell_post + post + pre += asm_shell_pre + '\n' + start_funcs_marker + post = end_funcs_marker + asm_shell_post + post minify_info = minifier.serialize() else: -- cgit v1.2.3-70-g09d2 From de3c3ca816dd92103802b9d222d00f561666208e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:17:14 -0800 Subject: for now, do not use rX as minified names, reserve that for registerize locals --- tools/js-optimizer.js | 2 +- tools/js_optimizer.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index fdc456f8..102ced8b 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1540,7 +1540,7 @@ function registerize(ast) { saved++; } else { reg = nextReg++; - fullNames[reg] = (asm ? (asmData.vars[name] ? 'd' : 'i') : 'r') + reg; // TODO: even smaller names + fullNames[reg] = (asm ? (asmData.vars[name] ? 'd' : 'i') : 'r') + reg; // XXX need to ensure we do not override used globals if (params[name]) paramRegs[reg] = 1; } varRegs[name] = reg; diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index bac693bf..6a2f4091 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -47,12 +47,14 @@ class Minifier: for a in init_possibles: for b in later_possibles: if len(self.names) >= MAX_NAMES: break + if a == 'r' and b in string.digits: continue # TODO: minify registerize names 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 + if a == 'r' and b in string.digits and c in string.digits: continue # TODO: minify registerize names curr = a + b + c if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names -- cgit v1.2.3-70-g09d2 From e0fe8d85edff16483f0fa1e82653f0415c703cf2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:31:56 -0800 Subject: fix temporary workaround for register names --- tools/js_optimizer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 6a2f4091..8c5edefb 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -47,14 +47,14 @@ class Minifier: for a in init_possibles: for b in later_possibles: if len(self.names) >= MAX_NAMES: break - if a == 'r' and b in string.digits: continue # TODO: minify registerize names + if a in 'id' and b in string.digits: continue # TODO: minify registerize names 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 - if a == 'r' and b in string.digits and c in string.digits: continue # TODO: minify registerize names + if a in 'id' and b in string.digits and c in string.digits: continue # TODO: minify registerize names curr = a + b + c if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names -- cgit v1.2.3-70-g09d2 From 0d0ce4f677f293697123d4e237ca446dbc3fcc27 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:53:17 -0800 Subject: fix another name collision --- tools/js_optimizer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 8c5edefb..fda5e77d 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -47,14 +47,14 @@ class Minifier: for a in init_possibles: for b in later_possibles: if len(self.names) >= MAX_NAMES: break - if a in 'id' and b in string.digits: continue # TODO: minify registerize names + if a in 'ida' and b in string.digits: continue # TODO: minify registerize names 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 - if a in 'id' and b in string.digits and c in string.digits: continue # TODO: minify registerize names + if a in 'ida' and b in string.digits and c in string.digits: continue # TODO: minify registerize names curr = a + b + c if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names @@ -167,6 +167,7 @@ EMSCRIPTEN_FUNCS(); post = end_funcs_marker + asm_shell_post + post minify_info = minifier.serialize() + #if DEBUG: print >> sys.stderr, 'minify info:', minify_info else: pre = '' post = '' -- cgit v1.2.3-70-g09d2 From f1bbf0244b08dce2c2bfb9fc507d6088dcb6a596 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Mar 2013 18:59:39 -0800 Subject: save 0.0 in asm shell minification --- tools/js_optimizer.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index fda5e77d..f8dfddf2 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -66,6 +66,8 @@ class Minifier: # to minify all global names, we receive a dictionary back, which is then # used by the function processors + shell = shell.replace('0.0', '13371337') # avoid uglify doing 0.0 => 0 + # Find all globals in the JS functions code self.globs = [m.group(2) for m in func_sig.finditer(self.js)] @@ -82,7 +84,8 @@ class Minifier: #print >> sys.stderr, "minified SHELL 3333333333333333", output, "\n44444444444444444444" code, metadata = output.split('// MINIFY_INFO:') self.globs = json.loads(metadata) - return code + return code.replace('13371337', '0.0') + def serialize(self): return json.dumps({ -- cgit v1.2.3-70-g09d2 From a43d5b5a146a4cfc654c2c1dbd05001e58977273 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 09:28:54 -0800 Subject: do not emit generated functions suffix when no longer needed --- tools/js_optimizer.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index f8dfddf2..d089a989 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -171,6 +171,9 @@ EMSCRIPTEN_FUNCS(); minify_info = minifier.serialize() #if DEBUG: print >> sys.stderr, 'minify info:', minify_info + # remove suffix if no longer needed + if 'last' in passes: + post = post.split(suffix_marker)[0] else: pre = '' post = '' -- cgit v1.2.3-70-g09d2 From 74a855a0d5a8d1708f47e6531a22ca6ae3f8f76e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 10:04:07 -0800 Subject: improve non-asm parsing of generated functions area to be identical in EMCC_DEBUG=1 and 2 --- tests/runner.py | 2 ++ tools/js_optimizer.py | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tests/runner.py b/tests/runner.py index 91260177..02558650 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7311,6 +7311,8 @@ def process(filename): return output + self.emcc_args += ['--minify', '0'] # to compare the versions + def do_test(): self.do_run(open(path_from_root('tests', 'openjpeg', 'codec', 'j2k_to_image.c'), 'r').read(), 'Successfully generated', # The real test for valid output is in image_compare diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index d089a989..b52f2324 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -148,12 +148,19 @@ def run_on_js(filename, passes, js_engine, jcache): if suffix: if not asm_registerize: pre = js[:start_funcs + len(start_funcs_marker)] - post = js[end_funcs:] + post = js[end_funcs + len(end_funcs_marker):] js = js[start_funcs + len(start_funcs_marker):end_funcs] if 'asm' not in passes: # can have Module[..] and inlining prevention code, push those to post - for line in js.split('\n'): + class Finals: + buf = [] + def process(line): if len(line) > 0 and not line.startswith((' ', 'function', '}')): - post = line + '\n' + post + Finals.buf.append(line) + return False + return True + js = '\n'.join(filter(process, js.split('\n'))) + post = '\n'.join(Finals.buf) + '\n' + post + post = end_funcs_marker + post else: # We need to split out the asm shell as well, for minification pre = js[:start_asm + len(start_asm_marker)] -- cgit v1.2.3-70-g09d2 From 9f9be7e02e6f8173cf883f01ccef71892b4e33e0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 13:30:46 -0800 Subject: compress asm shell --- tools/js_optimizer.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index b52f2324..94883a90 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -59,7 +59,7 @@ class Minifier: if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names - def minify_shell(self, shell): + def minify_shell(self, shell, compress): #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 @@ -79,7 +79,7 @@ class Minifier: f.write('// MINIFY_INFO:' + self.serialize()) f.close() - output = subprocess.Popen(self.js_engine + [JS_OPTIMIZER, temp_file, 'minifyGlobals', 'noPrintMetadata'], stdout=subprocess.PIPE).communicate()[0] + output = subprocess.Popen(self.js_engine + [JS_OPTIMIZER, temp_file, 'minifyGlobals', 'noPrintMetadata'] + (['compress'] if compress else []), stdout=subprocess.PIPE).communicate()[0] assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + output #print >> sys.stderr, "minified SHELL 3333333333333333", output, "\n44444444444444444444" code, metadata = output.split('// MINIFY_INFO:') @@ -171,7 +171,7 @@ EMSCRIPTEN_FUNCS(); js = js[start_funcs + len(start_funcs_marker):end_funcs] minifier = Minifier(js, js_engine) - asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell).split('EMSCRIPTEN_FUNCS();'); + asm_shell_pre, asm_shell_post = minifier.minify_shell(asm_shell, 'compress' in passes).split('EMSCRIPTEN_FUNCS();'); asm_shell_post = asm_shell_post.replace('});', '})'); pre += asm_shell_pre + '\n' + start_funcs_marker post = end_funcs_marker + asm_shell_post + post -- cgit v1.2.3-70-g09d2 From 0ecad78d552f20c7dfc454489df3eba61361fa06 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 15:47:41 -0800 Subject: remove limitations on minified names --- tools/js-optimizer.js | 2 +- tools/js_optimizer.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 5b2e6188..2b9064b2 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1454,7 +1454,7 @@ function registerize(ast) { var name = node[1]; var minified = minifierInfo.globals[name]; if (minified) { - assert(!localVars[name]); // locals must not shadow globals, or else we don't know which is which + assert(!localVars[name], name); // locals must not shadow globals, or else we don't know which is which if (localVars[minified]) { // trying to minify a global into a name used locally. rename all the locals var newName = '$_newLocal_' + (nextLocal++); diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 94883a90..98b34684 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -47,14 +47,12 @@ class Minifier: for a in init_possibles: for b in later_possibles: if len(self.names) >= MAX_NAMES: break - if a in 'ida' and b in string.digits: continue # TODO: minify registerize names 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 - if a in 'ida' and b in string.digits and c in string.digits: continue # TODO: minify registerize names curr = a + b + c if curr not in INVALID_3: self.names.append(curr) #print >> sys.stderr, self.names -- cgit v1.2.3-70-g09d2 From b7093afaf4bb9fa593d687d6c9646289e8d75cff Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 9 Mar 2013 16:50:41 -0800 Subject: do not wipe out everything after the generated functions suffix; fixes test_embind --- tools/js_optimizer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 98b34684..60093bca 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -118,7 +118,8 @@ def run_on_js(filename, passes, js_engine, jcache): suffix_start = js.find(suffix_marker) suffix = '' if suffix_start >= 0: - suffix = js[suffix_start:js.find('\n', suffix_start)] + '\n' + suffix_end = js.find('\n', suffix_start) + suffix = js[suffix_start:suffix_end] + '\n' # if there is metadata, we will run only on the generated functions. If there isn't, we will run on everything. generated = set(eval(suffix[len(suffix_marker)+1:])) @@ -178,7 +179,10 @@ EMSCRIPTEN_FUNCS(); #if DEBUG: print >> sys.stderr, 'minify info:', minify_info # remove suffix if no longer needed if 'last' in passes: - post = post.split(suffix_marker)[0] + suffix_start = post.find(suffix_marker) + suffix_end = post.find('\n', suffix_start) + post = post[:suffix_start] + post[suffix_end:] + else: pre = '' post = '' -- cgit v1.2.3-70-g09d2 From 1c25bb627bb43d2595dc59545d65d5a2ec83a9bf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 10:03:06 -0700 Subject: use whitelist of lines to forward out of generated functions area --- tools/js_optimizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 60093bca..ae7fe817 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -153,7 +153,7 @@ def run_on_js(filename, passes, js_engine, jcache): class Finals: buf = [] def process(line): - if len(line) > 0 and not line.startswith((' ', 'function', '}')): + if len(line) > 0 and (line.startswith('Module[') or line.endswith('["X"]=1;')): Finals.buf.append(line) return False return True -- cgit v1.2.3-70-g09d2 From a373820140dc019bb01561883380595ae8a1f739 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 10 Mar 2013 10:18:45 -0700 Subject: add 'progress' updates from multicore operations in emcc --- emscripten.py | 5 +++-- tools/js_optimizer.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'tools/js_optimizer.py') diff --git a/emscripten.py b/emscripten.py index 09a57e37..34a5b20f 100755 --- a/emscripten.py +++ b/emscripten.py @@ -33,7 +33,7 @@ NUM_CHUNKS_PER_CORE = 1.25 MIN_CHUNK_SIZE = 1024*1024 MAX_CHUNK_SIZE = float(os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or 'inf') # configuring this is just for debugging purposes -def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files)): +def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files, DEBUG)): ll = ''.join(funcs) + '\n' + meta funcs_file = temp_files.get('.func_%d.ll' % i).name open(funcs_file, 'w').write(ll) @@ -44,6 +44,7 @@ def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libr stdout=subprocess.PIPE, cwd=path_from_root('src')) tempfiles.try_delete(funcs_file) + if DEBUG: print >> sys.stderr, '.' return out def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, @@ -213,7 +214,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, if DEBUG: print >> sys.stderr, ' emscript: phase 2 working on %d chunks %s (intended chunk size: %.2f MB, meta: %.2f MB, forwarded: %.2f MB, total: %.2f MB)' % (len(chunks), ('using %d cores' % cores) if len(chunks) > 1 else '', chunk_size/(1024*1024.), len(meta)/(1024*1024.), len(forwarded_data)/(1024*1024.), total_ll_size/(1024*1024.)) commands = [ - (i, chunk, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files) + (i, chunk, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files, DEBUG) for i, chunk in enumerate(chunks) ] diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index ae7fe817..053f0dcd 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -100,6 +100,7 @@ def run_on_chunk(command): f = open(filename, 'w') f.write(output) f.close() + if DEBUG: print >> sys.stderr, '.' return filename def run_on_js(filename, passes, js_engine, jcache): -- cgit v1.2.3-70-g09d2 From c234f893b8ad4a4a71c4b3cb07da8bd2bb0d55cf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 11 Mar 2013 11:51:46 -0700 Subject: bump number of minified names --- tools/js_optimizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 053f0dcd..87fd0660 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -34,7 +34,7 @@ class Minifier: # Create list of valid short names - MAX_NAMES = 6000#0 + MAX_NAMES = 60000 INVALID_2 = set(['do', 'if', 'in']) INVALID_3 = set(['for', 'new', 'try', 'var', 'env']) -- cgit v1.2.3-70-g09d2 From 072aaa9ee5a48f005dea6467f9f5a6a89f26f65b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 12 Mar 2013 14:56:01 -0700 Subject: fix globalScope altering in runtimelink modules; fixes test_runtimelink --- tools/js_optimizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/js_optimizer.py') diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 87fd0660..1f1c1354 100644 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -154,7 +154,7 @@ def run_on_js(filename, passes, js_engine, jcache): class Finals: buf = [] def process(line): - if len(line) > 0 and (line.startswith('Module[') or line.endswith('["X"]=1;')): + if len(line) > 0 and (line.startswith(('Module[', 'if (globalScope)')) or line.endswith('["X"]=1;')): Finals.buf.append(line) return False return True -- cgit v1.2.3-70-g09d2