add a whitelist option for the emterpreter; #3129
This commit is contained in:
Родитель
4482858955
Коммит
7d5be1566c
4
emcc
4
emcc
|
@ -70,7 +70,7 @@ LIB_PREFIXES = ('', 'lib')
|
|||
|
||||
JS_CONTAINING_SUFFIXES = ('js', 'html')
|
||||
|
||||
DEFERRED_REPONSE_FILES = ('EMTERPRETIFY_BLACKLIST',)
|
||||
DEFERRED_REPONSE_FILES = ('EMTERPRETIFY_BLACKLIST', 'EMTERPRETIFY_WHITELIST')
|
||||
|
||||
# Mapping of emcc opt levels to llvm opt levels. We use llvm opt level 3 in emcc opt
|
||||
# levels 2 and 3 (emcc 3 is unsafe opts, so unsuitable for the only level to get
|
||||
|
@ -1555,7 +1555,7 @@ try:
|
|||
try:
|
||||
# move temp js to final position, alongside its mem init file
|
||||
shutil.move(final, js_target)
|
||||
args = [shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', memfile, json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST)]
|
||||
args = [shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', memfile, json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST), json.dumps(shared.Settings.EMTERPRETIFY_WHITELIST)]
|
||||
if shared.Settings.EMTERPRETIFY_ASYNC:
|
||||
args += ['ASYNC=1']
|
||||
if profiling:
|
||||
|
|
|
@ -576,6 +576,8 @@ var NO_DYNAMIC_EXECUTION = 0; // When enabled, we do not emit eval() and new Fun
|
|||
|
||||
var EMTERPRETIFY = 0; // Runs tools/emterpretify on the compiler output
|
||||
var EMTERPRETIFY_BLACKLIST = []; // Functions to not emterpret, that is, to run normally at full speed
|
||||
var EMTERPRETIFY_WHITELIST = []; // If this contains any functions, then only the functions in this list
|
||||
// are emterpreted (as if all the rest are blacklisted; this overrides the BLACKLIST)
|
||||
var EMTERPRETIFY_ASYNC = 0; // Allows sync code in the emterpreter, by saving the call stack, doing an async delay, and resuming it
|
||||
|
||||
var RUNNING_JS_OPTS = 0; // whether js opts will be run, after the main compiler
|
||||
|
|
|
@ -4378,6 +4378,29 @@ pass: error == ENOTDIR
|
|||
assert 'emterpret' not in get_func(src, '_main'), 'main is NOT emterpreted, it was blacklisted'
|
||||
assert 'emterpret' not in get_func(src, '_atoi'), 'atoi is NOT emterpreted either'
|
||||
|
||||
print 'whitelisting'
|
||||
|
||||
do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', ['-s', 'EMTERPRETIFY_WHITELIST=[]'])
|
||||
src = open('a.out.js').read()
|
||||
assert 'emterpret' in get_func(src, '_main'), 'main is emterpreted'
|
||||
assert 'function _atoi(' not in src, 'atoi is emterpreted and does not even have a trampoline, since only other emterpreted can reach it'
|
||||
|
||||
do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', ['-s', 'EMTERPRETIFY_WHITELIST=["_main"]'])
|
||||
src = open('a.out.js').read()
|
||||
assert 'emterpret' in get_func(src, '_main')
|
||||
assert 'emterpret' not in get_func(src, '_atoi'), 'atoi is not in whitelist, so it is not emterpreted'
|
||||
|
||||
do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', ['-s', 'EMTERPRETIFY_WHITELIST=["_main", "_atoi"]'])
|
||||
src = open('a.out.js').read()
|
||||
assert 'emterpret' in get_func(src, '_main')
|
||||
assert 'function _atoi(' not in src, 'atoi is emterpreted and does not even have a trampoline, since only other emterpreted can reach it'
|
||||
|
||||
open('whitelist.txt', 'w').write('["_main"]')
|
||||
do_emcc_test('fannkuch.cpp', ['5'], 'Pfannkuchen(5) = 7.', ['-s', 'EMTERPRETIFY_WHITELIST=@whitelist.txt'])
|
||||
src = open('a.out.js').read()
|
||||
assert 'emterpret' in get_func(src, '_main')
|
||||
assert 'emterpret' not in get_func(src, '_atoi'), 'atoi is not in whitelist, so it is not emterpreted'
|
||||
|
||||
do_test(r'''
|
||||
#include<stdio.h>
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ sys.argv = filter(handle_arg, sys.argv)
|
|||
# consts
|
||||
|
||||
BLACKLIST = set(['_malloc', '_free', '_memcpy', '_memmove', '_memset', 'copyTempDouble', 'copyTempFloat', '_strlen', 'stackAlloc', 'setThrew', 'stackRestore', 'setTempRet0', 'getTempRet0', 'stackSave', 'runPostSets', '_emscripten_autodebug_double', '_emscripten_autodebug_float', '_emscripten_autodebug_i8', '_emscripten_autodebug_i16', '_emscripten_autodebug_i32', '_emscripten_autodebug_i64', '_strncpy', '_strcpy', '_strcat', '_saveSetjmp', '_testSetjmp', '_emscripten_replace_memory', '_bitshift64Shl', '_bitshift64Ashr', '_bitshift64Lshr', 'setAsyncState', 'emtStackSave'])
|
||||
WHITELIST = []
|
||||
|
||||
OPCODES = [ # l, lx, ly etc - one of 256 locals
|
||||
'SET', # [lx, ly, 0] lx = ly (int or float, not double)
|
||||
|
@ -645,6 +646,13 @@ if __name__ == '__main__':
|
|||
assert temp[1] == '@'
|
||||
temp = open(temp[2:-1]).read()
|
||||
extra_blacklist = json.loads(temp)
|
||||
if len(sys.argv) >= 6:
|
||||
temp = sys.argv[5]
|
||||
if temp[0] == '"':
|
||||
# response file
|
||||
assert temp[1] == '@'
|
||||
temp = open(temp[2:-1]).read()
|
||||
WHITELIST = json.loads(temp)
|
||||
|
||||
BLACKLIST = set(list(BLACKLIST) + extra_blacklist)
|
||||
|
||||
|
@ -655,11 +663,15 @@ if __name__ == '__main__':
|
|||
|
||||
asm = asm_module.AsmModule(infile)
|
||||
|
||||
# sanity check on blacklist
|
||||
# process blacklist
|
||||
|
||||
for func in extra_blacklist:
|
||||
assert func in asm.funcs, 'requested blacklist of %s but it does not exist' % func
|
||||
|
||||
if len(WHITELIST) > 0:
|
||||
# we are using a whitelist: fill the blacklist with everything not whitelisted
|
||||
BLACKLIST = set([func for func in asm.funcs if func not in WHITELIST])
|
||||
|
||||
# decide which functions will be emterpreted, and find which are externally reachable (from outside other emterpreted code; those will need trampolines)
|
||||
|
||||
emterpreted_funcs = set([func for func in asm.funcs if func not in BLACKLIST and not func.startswith('dynCall_')])
|
||||
|
|
Загрузка…
Ссылка в новой задаче