diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/js-optimizer.js | 25 | ||||
-rw-r--r-- | tools/shared.py | 46 | ||||
-rwxr-xr-x | tools/source-maps/sourcemapper.js | 2 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-last-output.js | 28 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-last.js | 34 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 1 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 1 |
7 files changed, 108 insertions, 29 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 151e573a..d04807a7 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -188,12 +188,12 @@ function traverseChildren(node, traverse, pre, post, stack) { // was stopped, true. Otherwise undefined. function traverse(node, pre, post, stack) { var type = node[0], result, len; - var relevant = typeof node[0] === 'string'; + var relevant = typeof type === 'string'; if (relevant) { if (stack) len = stack.length; var result = pre(node, type, stack); if (result === true) return true; - if (Array.isArray(result)) node = result; // Continue processing on this node + if (result && result !== null) node = result; // Continue processing on this node if (stack && len === stack.length) stack.push(0); } if (result !== null) { @@ -584,6 +584,8 @@ function simplifyExpressionsPre(ast) { node[3] = value[2]; } } + } else if (type == 'sub' && node[1][0] == 'name' && /^FUNCTION_TABLE.*/.exec(node[1][1])) { + return null; // do not traverse subchildren here, we should not collapse 55 & 126. TODO: optimize this into a nonvirtual call (also because we lose some other opts here)! } }); @@ -2035,7 +2037,6 @@ function eliminate(ast, memSafe) { // examine body and note locals var hasSwitch = false; traverse(func, function(node, type) { - if (debug && type) type = type.toString(); if (type === 'var') { var node1 = node[1]; for (var i = 0; i < node1.length; i++) { @@ -2645,7 +2646,6 @@ function eliminate(ast, memSafe) { var has_num = false; var fail = false; traverse(node, function(subNode, subType) { - if (debug && subType) subType = subType.toString(); if (subType === 'binary') { if (subNode[1] !== '+') { fail = true; @@ -2807,6 +2807,23 @@ function asmLoopOptimizer(ast) { var stats = node[2][1]; var last = stats[stats.length-1]; if (last && last[0] === 'if' && !last[3] && last[2][0] === 'block' && last[2][1][0] && last[2][1][0][0] === 'break' && !last[2][1][0][1]) { + var abort = false; + var stack = 0; + traverse(stats, function(node, type) { + if (type == 'continue') { + if (stack == 0 || node[1]) { // abort if labeled (we do not analyze labels here yet), or a continue directly on us + abort = true; + return true; + } + } else if (type in LOOP) { + stack++; + } + }, function(node, type) { + if (type in LOOP) { + stack--; + } + }); + if (abort) return; var conditionToBreak = last[1]; stats.pop(); node[0] = 'do'; diff --git a/tools/shared.py b/tools/shared.py index 2a754d27..776001cd 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1,6 +1,7 @@ import shutil, time, os, sys, json, tempfile, copy, shlex, atexit, subprocess, hashlib, cPickle, re from subprocess import Popen, PIPE, STDOUT from tempfile import mkstemp +from distutils.spawn import find_executable import jsrun, cache, tempfiles from response_file import create_response_file import logging, platform @@ -204,25 +205,12 @@ else: config_file = '\n'.join(config_file) # autodetect some default paths config_file = config_file.replace('{{{ EMSCRIPTEN_ROOT }}}', __rootpath__) - llvm_root = '/usr/bin' - try: - llvm_root = os.path.dirname(Popen(['which', 'llvm-dis'], stdout=PIPE).communicate()[0].replace('\n', '')) - except: - pass + llvm_root = find_executable('llvm-dis') or '/usr/bin' config_file = config_file.replace('{{{ LLVM_ROOT }}}', llvm_root) - node = 'node' - try: - node = Popen(['which', 'node'], stdout=PIPE).communicate()[0].replace('\n', '') or \ - Popen(['which', 'nodejs'], stdout=PIPE).communicate()[0].replace('\n', '') or node - except: - pass + node = find_executable('node') or find_executable('nodejs') or 'node' config_file = config_file.replace('{{{ NODE }}}', node) - python = sys.executable or 'python' - try: - python = Popen(['which', 'python2'], stdout=PIPE).communicate()[0].replace('\n', '') or \ - Popen(['which', 'python'], stdout=PIPE).communicate()[0].replace('\n', '') or python - except: - pass + python = find_executable('python2') or find_executable('python') or \ + sys.executable or 'python' config_file = config_file.replace('{{{ PYTHON }}}', python) # write @@ -295,7 +283,7 @@ def check_node_version(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.5.1' +EMSCRIPTEN_VERSION = '1.5.3' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() @@ -324,6 +312,7 @@ def check_sanity(force=False): if reason: logging.warning('(Emscripten: %s, clearing cache)' % reason) Cache.erase() + force = False # the check actually failed, so definitely write out the sanity file, to avoid others later seeing failures too # some warning, not fatal checks - do them even if EM_IGNORE_SANITY is on check_llvm_version() @@ -944,7 +933,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e # Finish link actual_files = unique_ordered(actual_files) # tolerate people trying to link a.so a.so etc. - logging.debug('emcc: llvm-linking: %s', actual_files) + logging.debug('emcc: llvm-linking: %s to %s', actual_files, target) # check for too-long command line link_cmd = [LLVM_LINK] + actual_files + ['-o', target] @@ -1111,7 +1100,9 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e @staticmethod def get_safe_internalize(): - exports = ','.join(map(lambda exp: exp[1:], expand_response(Settings.EXPORTED_FUNCTIONS))) + exps = expand_response(Settings.EXPORTED_FUNCTIONS) + if '_malloc' not in exps: exps.append('_malloc') # needed internally, even if user did not add to EXPORTED_FUNCTIONS + exports = ','.join(map(lambda exp: exp[1:], exps)) # internalize carefully, llvm 3.2 will remove even main if not told not to return ['-internalize', '-internalize-public-api-list=' + exports] @@ -1293,9 +1284,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e emcc_debug = os.environ.get('EMCC_DEBUG') if emcc_debug: del os.environ['EMCC_DEBUG'] - emcc_optimize_normally = os.environ.get('EMCC_OPTIMIZE_NORMALLY') - if emcc_optimize_normally: del os.environ['EMCC_OPTIMIZE_NORMALLY'] - def make(opt_level): raw = relooper + '.raw.js' Building.emcc(os.path.join('relooper', 'Relooper.cpp'), ['-I' + os.path.join('relooper'), '--post-js', @@ -1326,7 +1314,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e finally: os.chdir(curr) if emcc_debug: os.environ['EMCC_DEBUG'] = emcc_debug - if emcc_optimize_normally: os.environ['EMCC_OPTIMIZE_NORMALLY'] = emcc_optimize_normally if not ok: logging.error('bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten') 1/0 @@ -1392,6 +1379,17 @@ def execute(cmd, *args, **kw): logging.error('Invoking Process failed: <<< ' + cmd + ' >>>') raise +def check_execute(cmd, *args, **kw): + # TODO: use in more places. execute doesn't actually check that return values + # are nonzero + try: + kw['stderr'] = STDOUT + subprocess.check_output(cmd, *args, **kw) + logging.debug("Successfuly executed %s" % " ".join(cmd)) + except subprocess.CalledProcessError as e: + logging.error("'%s' failed with output:\n%s" % (" ".join(e.cmd), e.output)) + raise + def suffix(name): parts = name.split('.') if len(parts) > 1: diff --git a/tools/source-maps/sourcemapper.js b/tools/source-maps/sourcemapper.js index 0001e7c7..fa908900 100755 --- a/tools/source-maps/sourcemapper.js +++ b/tools/source-maps/sourcemapper.js @@ -110,7 +110,7 @@ function generateMap(mappings, sourceRoot, mapFileBaseName, generatedLineOffset) try { generator.setSourceContent(originalFileName, fs.readFileSync(rootedPath, 'utf-8')); } catch (e) { - console.warn("Unable to find original file for " + originalFileName + + console.warn("sourcemapper: Unable to find original file for " + originalFileName + " at " + rootedPath); } } diff --git a/tools/test-js-optimizer-asm-last-output.js b/tools/test-js-optimizer-asm-last-output.js index cbc0a4d3..0f95d544 100644 --- a/tools/test-js-optimizer-asm-last-output.js +++ b/tools/test-js-optimizer-asm-last-output.js @@ -42,5 +42,33 @@ function looop() { do { do_it(); } while (x()); + while (1) { + do_it(); + if (a()) continue; + if (!x()) { + break; + } + } + do { + do_it(); + do { + if (a()) continue; + } while (b()); + } while (x()); + do { + do_it(); + while (b()) { + if (a()) continue; + } + } while (x()); + X : while (1) { + do_it(); + while (b()) { + if (a()) continue X; + } + if (!x()) { + break; + } + } } diff --git a/tools/test-js-optimizer-asm-last.js b/tools/test-js-optimizer-asm-last.js index 6331879e..05e1049e 100644 --- a/tools/test-js-optimizer-asm-last.js +++ b/tools/test-js-optimizer-asm-last.js @@ -51,6 +51,40 @@ function looop() { break; } } + while (1) { + do_it(); + if (a()) continue; // we cannot move to do-while, continue will hit the while check + if (!x()) { + break; + } + } + while (1) { + do_it(); + do { + if (a()) continue; // ok to optimize, continue is not for us + } while (b()); + if (!x()) { + break; + } + } + while (1) { + do_it(); + while (b()) { + if (a()) continue; // also ok to optimize, continue is not for us + } + if (!x()) { + break; + } + } + X: while (1) { + do_it(); + while (b()) { + if (a()) continue X; // not ok to optimize + } + if (!x()) { + break; + } + } } // EMSCRIPTEN_GENERATED_FUNCTIONS: ["finall", "looop"] diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 2cd8d407..301a2ec8 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -19,6 +19,7 @@ function a() { f(g() | 0 & -1); f((g() | 0) >> 2); $56 = _fcntl() | 0 | 1; + FUNCTION_TABLE_ii[55 & 127]() | 0; } function b($this, $__n) { $this = $this | 0; diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index ca7d2894..c7c92124 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -20,6 +20,7 @@ function a() { f(g() | 0 & -1); f((g() | 0) >> 2); $56 = (_fcntl() | 0) | 1; + FUNCTION_TABLE_ii[55 & 127]() | 0; } function b($this, $__n) { $this = $this | 0; |