add explicit YIELDLIST to avoid hacks regarding running code during a sleep_with_yield

This commit is contained in:
Alon Zakai 2015-03-09 15:56:46 -07:00
Родитель cd601d76b8
Коммит f278a3ee2b
4 изменённых файлов: 12 добавлений и 6 удалений

Просмотреть файл

@ -243,7 +243,6 @@ mergeInto(LibraryManager.library, {
// copy the stack back in and resume
HEAP32.set(stack, EMTSTACKTOP>>2);
#if ASSERTIONS
EmterpreterAsync.setState(0); // set it to 0 just so stackSave is ok to run
assert(stacktop === asm.stackSave()); // nothing should have modified the stack meanwhile
#endif
EmterpreterAsync.setState(2);

Просмотреть файл

@ -33,7 +33,13 @@ int main() {
EM_ASM({
window.onerror = function(err) {
assert(err.toString().indexOf('This error happened during an emterpreter-async save or load of the stack') > 0, 'expect good error message');
Module._finish(1);
// manually REPORT_RESULT; we can't call back into native code at this point, assertions would trigger
xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:8888/report_result?1");
xhr.onload = xhr.onerror = function() {
window.close();
};
xhr.send();
};
});

Просмотреть файл

@ -57,6 +57,7 @@ sys.argv = filter(handle_arg, sys.argv)
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 = []
YIELDLIST = ['stackSave'] # functions which are ok to run while doing a sleep_with_yield.
SYNC_FUNCS = set(['_emscripten_sleep', '_emscripten_sleep_with_yield', '_emscripten_wget_data', '_emscripten_idb_load', '_emscripten_idb_store', '_emscripten_idb_delete'])
@ -696,8 +697,7 @@ function emterpret%s(pc) {
'' if not zero else '_z',
'sp = 0, ' if not zero else '',
'' if not ASYNC and not MEMORY_SAFE else 'var ld = +0;',
'' if not ASYNC else 'HEAP32[EMTSTACKTOP>>2] = pc;\n if ((asyncState|0) == 1) asyncState = 0;\n', # other code running between a save and resume can see state 1, just reset
# (optimally we should flip it to 0 at the bottom of the saving stack)
'' if not ASYNC else 'HEAP32[EMTSTACKTOP>>2] = pc;\n',
push_stacktop(zero),
ROPCODES['FUNC'],
(''' EMTSTACKTOP = EMTSTACKTOP + (lx ''' + (' + 1 ' if ASYNC else '') + '''<< 3) | 0;
@ -831,7 +831,7 @@ if __name__ == '__main__':
external_emterpreted_funcs = filter(lambda func: func in tabled_funcs or func in exported_funcs or func in reachable_funcs, emterpreted_funcs)
# process functions, generating bytecode
shared.Building.js_optimizer(infile, ['emterpretify'], extra_info={ 'emterpretedFuncs': list(emterpreted_funcs), 'externalEmterpretedFuncs': list(external_emterpreted_funcs), 'opcodes': OPCODES, 'ropcodes': ROPCODES, 'ASYNC': ASYNC, 'PROFILING': PROFILING, 'ASSERTIONS': ASSERTIONS }, output_filename=temp, just_concat=True)
shared.Building.js_optimizer(infile, ['emterpretify'], extra_info={ 'emterpretedFuncs': list(emterpreted_funcs), 'externalEmterpretedFuncs': list(external_emterpreted_funcs), 'opcodes': OPCODES, 'ropcodes': ROPCODES, 'ASYNC': ASYNC, 'PROFILING': PROFILING, 'ASSERTIONS': ASSERTIONS, 'yieldFuncs': YIELDLIST }, output_filename=temp, just_concat=True)
# load the module and modify it
asm = asm_module.AsmModule(temp)

Просмотреть файл

@ -6156,6 +6156,7 @@ function emterpretify(ast) {
var ASYNC = extraInfo.ASYNC;
var PROFILING = extraInfo.PROFILING;
var ASSERTIONS = extraInfo.ASSERTIONS;
var yieldFuncs = set(extraInfo.yieldFuncs);
var RELATIVE_BRANCHES = set('BR', 'BRT', 'BRF');
var ABSOLUTE_BRANCHES = set('BRA', 'BRTA', 'BRFA');
@ -7438,7 +7439,7 @@ function emterpretify(ast) {
if (ignore) {
// we are not emterpreting this function
if (ASYNC && ASSERTIONS && !/^dynCall_/.test(func[1])) {
if (ASYNC && ASSERTIONS && !/^dynCall_/.test(func[1]) && !(func[1] in yieldFuncs)) {
// we need to be careful to never enter non-emterpreted code while doing an async save/restore,
// which is what happens if non-emterpreted code is on the stack while we attempt to save.
// note that we special-case dynCall, which *can* be on the stack, they are just bridges; what