add --closure 2 option, to run closure even on the asm.js output
This commit is contained in:
Родитель
ae14052569
Коммит
919556db48
24
emcc
24
emcc
|
@ -920,8 +920,11 @@ try:
|
|||
assert not (shared.Settings.NO_DYNAMIC_EXECUTION and closure), 'cannot have both NO_DYNAMIC_EXECUTION and closure compiler enabled at the same time'
|
||||
|
||||
if closure:
|
||||
shared.Settings.CLOSURE_COMPILER = 1
|
||||
shared.Settings.CLOSURE_COMPILER = closure
|
||||
assert os.path.exists(shared.CLOSURE_COMPILER), logging.error('fatal: Closure compiler (%s) does not exist', shared.CLOSURE_COMPILER)
|
||||
if closure == 2 and shared.Settings.ASM_JS == 1:
|
||||
logging.warning('not all asm.js optimizations are possible with --closure 2, disabling those')
|
||||
shared.Settings.ASM_JS = 2
|
||||
|
||||
assert shared.LLVM_TARGET in shared.COMPILER_OPTS
|
||||
if shared.LLVM_TARGET == 'i386-pc-linux-gnu':
|
||||
|
@ -1352,7 +1355,7 @@ try:
|
|||
js_optimizer_extra_info = {}
|
||||
|
||||
if opt_level >= 1 and js_opts:
|
||||
logging.debug('running pre-closure post-opts')
|
||||
logging.debug('running js post-opts')
|
||||
|
||||
if DEBUG == '2':
|
||||
# Clean up the syntax a bit
|
||||
|
@ -1399,28 +1402,37 @@ try:
|
|||
js_optimizer_queue += ['outline']
|
||||
js_optimizer_extra_info['sizeToOutline'] = shared.Settings.OUTLINING_LIMIT
|
||||
|
||||
if opt_level >= 2 and (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and debug_level < 3:
|
||||
if opt_level >= 2 and (not closure or shared.Settings.ASM_JS or closure == 2) and shared.Settings.RELOOP and debug_level < 3:
|
||||
if shared.Settings.ASM_JS and opt_level >= 3:
|
||||
js_optimizer_queue += ['registerizeHarder']
|
||||
else:
|
||||
js_optimizer_queue += ['registerize']
|
||||
|
||||
if opt_level >= 2:
|
||||
if debug_level < 2 and shared.Settings.ASM_JS:
|
||||
if debug_level < 2 and shared.Settings.ASM_JS and not closure == 2:
|
||||
js_optimizer_queue += ['minifyNames']
|
||||
if emit_symbol_map: js_optimizer_queue += ['symbolMap='+target+'.symbols']
|
||||
if debug_level == 0: js_optimizer_queue += ['minifyWhitespace']
|
||||
|
||||
if shared.Settings.ASM_JS:
|
||||
if closure:
|
||||
if closure == 1:
|
||||
js_optimizer_queue += ['closure']
|
||||
elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE:
|
||||
elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE and not closure:
|
||||
js_optimizer_queue += ['cleanup']
|
||||
|
||||
if not shared.Settings.SIDE_MODULE: js_optimizer_queue += ['last'] # side modules are not finalized until after relocation
|
||||
|
||||
flush_js_optimizer_queue()
|
||||
|
||||
if shared.Settings.ASM_JS and closure == 2:
|
||||
flush_js_optimizer_queue()
|
||||
|
||||
logging.debug('running closure')
|
||||
# no need to add this to js_transform_tempfiles, because closure and
|
||||
# debug_level > 0 are never simultaneously true
|
||||
final = shared.Building.closure_compiler(final, pretty=debug_level >= 1)
|
||||
if DEBUG: save_intermediate('closure')
|
||||
|
||||
log_time('js opts')
|
||||
|
||||
# Remove some trivial whitespace # TODO: do not run when compress has already been done on all parts of the code
|
||||
|
|
|
@ -1124,12 +1124,24 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
|
|||
asm_setup += '\n' + shared.JS.make_extcall(sig) + '\n'
|
||||
basic_funcs.append('extCall_%s' % sig)
|
||||
|
||||
def quote(prop):
|
||||
if settings['CLOSURE_COMPILER'] == 2:
|
||||
return "'" + prop + "'"
|
||||
else:
|
||||
return prop
|
||||
|
||||
def access_quote(prop):
|
||||
if settings['CLOSURE_COMPILER'] == 2:
|
||||
return "['" + prop + "']"
|
||||
else:
|
||||
return '.' + prop
|
||||
|
||||
# calculate exports
|
||||
exported_implemented_functions = list(exported_implemented_functions) + metadata['initializers']
|
||||
exported_implemented_functions.append('runPostSets')
|
||||
exports = []
|
||||
for export in exported_implemented_functions + asm_runtime_funcs + function_tables:
|
||||
exports.append("%s: %s" % (export, export))
|
||||
exports.append(quote(export) + ": " + export)
|
||||
exports = '{ ' + ', '.join(exports) + ' }'
|
||||
# calculate globals
|
||||
try:
|
||||
|
@ -1141,9 +1153,9 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
|
|||
global_funcs = list(set([key for key, value in forwarded_json['Functions']['libraryFunctions'].iteritems() if value != 2]).difference(set(global_vars)).difference(implemented_functions))
|
||||
def math_fix(g):
|
||||
return g if not g.startswith('Math_') else g.split('_')[1]
|
||||
asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global.' + g + ';\n' for g in maths]) + \
|
||||
''.join([' var ' + g + '=env.' + math_fix(g) + ';\n' for g in basic_funcs + global_funcs])
|
||||
asm_global_vars = ''.join([' var ' + g + '=env.' + g + '|0;\n' for g in basic_vars + global_vars])
|
||||
asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global' + access_quote(g) + ';\n' for g in maths]) + \
|
||||
''.join([' var ' + g + '=env' + access_quote(math_fix(g)) + ';\n' for g in basic_funcs + global_funcs])
|
||||
asm_global_vars = ''.join([' var ' + g + '=env' + access_quote(g) + '|0;\n' for g in basic_vars + global_vars])
|
||||
# In linkable modules, we need to add some explicit globals for global variables that can be linked and used across modules
|
||||
if settings.get('MAIN_MODULE') or settings.get('SIDE_MODULE'):
|
||||
assert settings.get('TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'), 'TODO: support x86 target when linking modules (needs offset of 4 and not 8 here)'
|
||||
|
@ -1167,6 +1179,7 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
|
|||
return real_''' + s + '''.apply(null, arguments);
|
||||
};
|
||||
''' for s in exported_implemented_functions if s not in ['_malloc', '_free', '_memcpy', '_memset']])
|
||||
|
||||
receiving += ';\n'.join(['var ' + s + ' = Module["' + s + '"] = asm["' + s + '"]' for s in exported_implemented_functions + function_tables])
|
||||
|
||||
# finalize
|
||||
|
@ -1184,15 +1197,23 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
|
|||
// EMSCRIPTEN_START_ASM
|
||||
var asm = (function(global, env, buffer) {
|
||||
%s
|
||||
var HEAP8 = new global.Int8Array(buffer);
|
||||
var HEAP16 = new global.Int16Array(buffer);
|
||||
var HEAP32 = new global.Int32Array(buffer);
|
||||
var HEAPU8 = new global.Uint8Array(buffer);
|
||||
var HEAPU16 = new global.Uint16Array(buffer);
|
||||
var HEAPU32 = new global.Uint32Array(buffer);
|
||||
var HEAPF32 = new global.Float32Array(buffer);
|
||||
var HEAPF64 = new global.Float64Array(buffer);
|
||||
''' % (asm_setup, "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';") + '\n' + asm_global_vars + '''
|
||||
var HEAP8 = new global%s(buffer);
|
||||
var HEAP16 = new global%s(buffer);
|
||||
var HEAP32 = new global%s(buffer);
|
||||
var HEAPU8 = new global%s(buffer);
|
||||
var HEAPU16 = new global%s(buffer);
|
||||
var HEAPU32 = new global%s(buffer);
|
||||
var HEAPF32 = new global%s(buffer);
|
||||
var HEAPF64 = new global%s(buffer);
|
||||
''' % (asm_setup, "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';",
|
||||
access_quote('Int8Array'),
|
||||
access_quote('Int16Array'),
|
||||
access_quote('Int32Array'),
|
||||
access_quote('Uint8Array'),
|
||||
access_quote('Uint16Array'),
|
||||
access_quote('Uint32Array'),
|
||||
access_quote('Float32Array'),
|
||||
access_quote('Float64Array')) + '\n' + asm_global_vars + '''
|
||||
var __THREW__ = 0;
|
||||
var threwValue = 0;
|
||||
var setjmpId = 0;
|
||||
|
|
|
@ -218,11 +218,16 @@ Options that are modified or new in *emcc* are listed below:
|
|||
* "1": Run closure compiler. This greatly reduces code size
|
||||
and may in some cases increase runtime speed (although the
|
||||
opposite can also occur). Note that it takes time to run, and
|
||||
may require some changes to the code.
|
||||
may require some changes to the code. In **asm.js** mode,
|
||||
closure will only be used on the 'shell' code around the
|
||||
compiled code (the compiled code will be processed by the
|
||||
custom **asm.js** minifier).
|
||||
|
||||
In **asm.js** mode, closure will only be used on the 'shell' code
|
||||
around the compiled code (the compiled code will be processed by
|
||||
the custom **asm.js** minifier).
|
||||
* "2": Run closure compiler on *all* the emitted code, even on
|
||||
**asm.js** output in **asm.js** mode. This can further reduce
|
||||
code size, but does prevent a significant amount of **asm.js**
|
||||
optimizations, so it is not recommended unless you want to
|
||||
reduce code size at all costs.
|
||||
|
||||
Note: * If closure compiler hits an out-of-memory, try adjusting
|
||||
|
||||
|
|
|
@ -158,9 +158,8 @@ Options that are modified or new in *emcc* are listed below:
|
|||
Runs the :term:`Closure Compiler`. Possible ``on`` values are:
|
||||
|
||||
- ``0``: No closure compiler (default in ``-O2`` and below).
|
||||
- ``1``: Run closure compiler. This greatly reduces code size and may in some cases increase runtime speed (although the opposite can also occur). Note that it takes time to run, and may require some changes to the code.
|
||||
|
||||
In **asm.js** mode, closure will only be used on the 'shell' code around the compiled code (the compiled code will be processed by the custom **asm.js** minifier).
|
||||
- ``1``: Run closure compiler. This greatly reduces code size and may in some cases increase runtime speed (although the opposite can also occur). Note that it takes time to run, and may require some changes to the code. In **asm.js** mode, closure will only be used on the 'shell' code around the compiled code (the compiled code will be processed by the custom **asm.js** minifier).
|
||||
- ``2``: Run closure compiler on *all* the emitted code, even on **asm.js** output in **asm.js** mode. This can further reduce code size, but does prevent a significant amount of **asm.js** optimizations, so it is not recommended unless you want to reduce code size at all costs.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -3978,12 +3978,13 @@ main(const int argc, const char * const * const argv)
|
|||
test(['-O1'])
|
||||
|
||||
def test_no_nuthin(self):
|
||||
def test(opts, ratio):
|
||||
def test(opts, ratio, absolute):
|
||||
print opts
|
||||
def get_size(name):
|
||||
return os.stat(name).st_size
|
||||
sizes = {}
|
||||
def do(name, moar_opts):
|
||||
self.clear()
|
||||
Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', name + '.js'] + opts + moar_opts).communicate()
|
||||
sizes[name] = get_size(name + '.js')
|
||||
self.assertContained('hello, world!', run_js(name + '.js'))
|
||||
|
@ -3997,10 +3998,12 @@ main(const int argc, const char * const * const argv)
|
|||
assert sizes['no_nuthin'] < sizes['no_fs']
|
||||
assert sizes['no_nuthin'] < sizes['no_browser']
|
||||
assert sizes['no_nuthin'] < ratio*sizes['normal']
|
||||
test([], 0.66)
|
||||
test(['-O1'], 0.66)
|
||||
test(['-O2'], 0.50)
|
||||
test(['-O3', '--closure', '1'], 0.60)
|
||||
assert sizes['no_nuthin'] < absolute
|
||||
test([], 0.66, 250000)
|
||||
test(['-O1'], 0.66, 225000)
|
||||
test(['-O2'], 0.50, 75000)
|
||||
test(['-O3', '--closure', '1'], 0.60, 60000)
|
||||
test(['-O3', '--closure', '2'], 0.60, 40000) # might change now and then
|
||||
|
||||
def test_stat_fail_alongtheway(self):
|
||||
open('src.cpp', 'w').write(r'''
|
||||
|
|
Загрузка…
Ссылка в новой задаче