Skip to content

Commit fe87592

Browse files
committed
remove emterpreter YIELDLIST - it complicates the mental model and is not worth it for the rather slim amount of benefit it provides
1 parent 5d970d5 commit fe87592

7 files changed

Lines changed: 14 additions & 59 deletions

File tree

emcc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1562,7 +1562,7 @@ try:
15621562
try:
15631563
# move temp js to final position, alongside its mem init file
15641564
shutil.move(final, js_target)
1565-
args = [shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST), json.dumps(shared.Settings.EMTERPRETIFY_WHITELIST), json.dumps(shared.Settings.EMTERPRETIFY_YIELDLIST), str(shared.Settings.SWAPPABLE_ASM_MODULE)]
1565+
args = [shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST), json.dumps(shared.Settings.EMTERPRETIFY_WHITELIST), '', str(shared.Settings.SWAPPABLE_ASM_MODULE)]
15661566
if shared.Settings.EMTERPRETIFY_ASYNC:
15671567
args += ['ASYNC=1']
15681568
if shared.Settings.EMTERPRETIFY_ADVISE:

src/library_async.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ mergeInto(LibraryManager.library, {
222222
#if ASSERTIONS
223223
abortDecorators.push(function(output, what) {
224224
if (EmterpreterAsync.state !== 0) {
225-
return output + '\nThis error happened during an emterpreter-async save or load of the stack. Was there non-emterpreted code on the stack during save (which is unallowed)? You may want to adjust EMTERPRETIFY_BLACKLIST, EMTERPRETIFY_WHITELIST, or EMTERPRETIFY_YIELDLIST (to consider certain functions ok to run during an emscripten_sleep_with_yield).\nThis is what the stack looked like when we tried to save it: ' + [EmterpreterAsync.state, EmterpreterAsync.saveStack];
225+
return output + '\nThis error happened during an emterpreter-async save or load of the stack. Was there non-emterpreted code on the stack during save (which is unallowed)? You may want to adjust EMTERPRETIFY_BLACKLIST, EMTERPRETIFY_WHITELIST.\nThis is what the stack looked like when we tried to save it: ' + [EmterpreterAsync.state, EmterpreterAsync.saveStack];
226226
}
227227
return output;
228228
});

src/settings.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -464,22 +464,11 @@ var EMTERPRETIFY = 0; // Runs tools/emterpretify on the compiler output
464464
var EMTERPRETIFY_BLACKLIST = []; // Functions to not emterpret, that is, to run normally at full speed
465465
var EMTERPRETIFY_WHITELIST = []; // If this contains any functions, then only the functions in this list
466466
// are emterpreted (as if all the rest are blacklisted; this overrides the BLACKLIST)
467-
var EMTERPRETIFY_YIELDLIST = []; // A list of functions that are allowed to run during while sleeping. Typically this is
468-
// during emscripten_sleep_with_yield , but also you may need to add methods to this list
469-
// for things like event handling (an SDL EventHandler will be called from the event, directly -
470-
// if we do that later, you lose out on the whole point of an EventHandler, which is to let
471-
// you react to key presses in order to launch fullscreen, etc.).
472-
// Functions in the yield list do not trigger asserts checking on running during a sleep,
473-
// in ASSERTIONS builds,
474467
var EMTERPRETIFY_ASYNC = 0; // Allows sync code in the emterpreter, by saving the call stack, doing an async delay, and resuming it
475468
var EMTERPRETIFY_ADVISE = 0; // Performs a static analysis to suggest which functions should be run in the emterpreter, as it
476469
// appears they can be on the stack when a sync function is called in the EMTERPRETIFY_ASYNC option.
477470
// After showing the suggested list, compilation will halt. You can apply the provided list as an
478471
// emcc argument when compiling later.
479-
// This will also advise on the YIELDLIST, if it contains at least one value (it then reports
480-
// all things reachable from that function, as they may need to be in the YIELDLIST as well).
481-
// Note that this depends on things like inlining. If you run this with different inlining than
482-
// when you use the list, it might not work.
483472

484473
var RUNNING_JS_OPTS = 0; // whether js opts will be run, after the main compiler
485474
var BOOTSTRAPPING_STRUCT_INFO = 0; // whether we are in the generate struct_info bootstrap phase

tests/test_browser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ def test_sdl_key(self):
621621
]:
622622
for emterps in [
623623
[],
624-
['-DTEST_SLEEP', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-s', 'ASSERTIONS=1', '-s', 'EMTERPRETIFY_YIELDLIST=["_EventHandler"]', '-s', "SAFE_HEAP=1"]
624+
['-DTEST_SLEEP', '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-s', 'ASSERTIONS=1', '-s', "SAFE_HEAP=1"]
625625
]:
626626
print delay, defines, emterps
627627
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('''
@@ -2400,7 +2400,7 @@ def test_emterpreter_async_sleep2(self):
24002400
self.btest('emterpreter_async_sleep2.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-Oz'])
24012401

24022402
def test_sdl_audio_beep_sleep(self):
2403-
self.btest('sdl_audio_beep_sleep.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-Os', '-s', 'ASSERTIONS=1', '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-profiling', '-s', 'EMTERPRETIFY_YIELDLIST=["__Z14audio_callbackPvPhi", "__ZN6Beeper15generateSamplesIhEEvPT_i", "__ZN6Beeper15generateSamplesIsEEvPT_i"]', '-s', 'SAFE_HEAP=1'])
2403+
self.btest('sdl_audio_beep_sleep.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-Os', '-s', 'ASSERTIONS=1', '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-profiling', '-s', 'SAFE_HEAP=1'])
24042404

24052405
def test_mainloop_reschedule(self):
24062406
self.btest('mainloop_reschedule.cpp', '1', args=['-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-Os'])

tests/test_other.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4418,13 +4418,6 @@ def test_emterpreter_advise(self):
44184418

44194419
out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'emterpreter_advise_funcptr.cpp'), '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-s', 'EMTERPRETIFY_ADVISE=1'], stdout=PIPE).communicate()
44204420
self.assertContained('-s EMTERPRETIFY_WHITELIST=\'["__Z4posti", "__Z5post2i", "__Z6middlev", "__Z7sleeperv", "__Z8recurserv", "_main"]\'', out)
4421-
self.assertNotContained('EMTERPRETIFY_YIELDLIST', out);
4422-
4423-
out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'emterpreter_advise_funcptr.cpp'), '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-s', 'EMTERPRETIFY_ADVISE=1', '-s', 'EMTERPRETIFY_YIELDLIST=["__Z6middlev"]'], stdout=PIPE).communicate()
4424-
self.assertContained('-s EMTERPRETIFY_YIELDLIST=\'["__Z6middlev", "__Z7siblingii", "__Z7sleeperv", "__Z8recurserv", "_printf"]\'', out)
4425-
4426-
out, err = Popen([PYTHON, EMCC, path_from_root('tests', 'emterpreter_advise_funcptr.cpp'), '-s', 'EMTERPRETIFY=1', '-s', 'EMTERPRETIFY_ASYNC=1', '-s', 'EMTERPRETIFY_ADVISE=1', '-s', 'EMTERPRETIFY_YIELDLIST=["__Z3pref"]'], stdout=PIPE).communicate()
4427-
self.assertContained('-s EMTERPRETIFY_YIELDLIST=\'["__Z3pref", "__Z7siblingii", "_printf"]\'', out)
44284421

44294422
def test_link_with_a_static(self):
44304423
for args in [[], ['-O2']]:

tools/emterpretify.py

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ def handle_arg(arg):
5757

5858
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'])
5959
WHITELIST = []
60-
YIELDLIST = ['stackSave', 'stackRestore', 'stackAlloc', 'setThrew', '_memset'] # functions which are ok to run while doing a sleep_with_yield.
6160

6261
SYNC_FUNCS = set(['_emscripten_sleep', '_emscripten_sleep_with_yield', '_emscripten_wget_data', '_emscripten_idb_load', '_emscripten_idb_store', '_emscripten_idb_delete'])
6362

@@ -703,8 +702,6 @@ def process(code):
703702
infile = sys.argv[1]
704703
outfile = sys.argv[2]
705704

706-
original_yieldlist = YIELDLIST
707-
708705
extra_blacklist = []
709706
if len(sys.argv) >= 4:
710707
temp = sys.argv[3]
@@ -723,13 +720,6 @@ def process(code):
723720
WHITELIST = json.loads(temp)
724721

725722
if len(sys.argv) >= 6:
726-
temp = sys.argv[5]
727-
if temp[0] == '"':
728-
# response file
729-
assert temp[1] == '@'
730-
temp = open(temp[2:-1]).read()
731-
YIELDLIST = YIELDLIST + json.loads(temp)
732-
733723
if len(sys.argv) >= 7:
734724
SWAPPABLE = int(sys.argv[6])
735725

@@ -774,23 +764,6 @@ def process(code):
774764
print "Suggested list of functions to run in the emterpreter:"
775765
print " -s EMTERPRETIFY_WHITELIST='" + str(sorted(list(advised))).replace("'", '"') + "'"
776766
print "(%d%% out of %d functions)" % (int((100.0*len(advised))/len(can_call)), len(can_call))
777-
if len(YIELDLIST) > len(original_yieldlist):
778-
# advise on the yield list as well. Anything a yield function can reach, likely needs to also be a yield function
779-
YIELD_IGNORE = set(['abort'])
780-
to_check = list(YIELDLIST)
781-
advised = set([str(f) for f in YIELDLIST])
782-
while len(to_check) > 0:
783-
curr = to_check.pop()
784-
if curr not in can_call: continue
785-
for next in can_call[curr]:
786-
if next not in advised:
787-
advised.add(str(next))
788-
to_check.append(next)
789-
advised = [next for next in advised if not is_dyn_call(next) and not is_function_table(next) and not next in original_yieldlist and next not in SYNC_FUNCS and next not in YIELD_IGNORE and next[0] == '_']
790-
print
791-
print "Suggested list of yield functions for the emterpreter:"
792-
print " -s EMTERPRETIFY_YIELDLIST='" + str(sorted(list(advised))).replace("'", '"') + "'"
793-
print "(%d%% out of %d functions)" % (int((100.0*len(advised))/len(can_call)), len(can_call))
794767
sys.exit(0)
795768

796769
BLACKLIST = set(list(BLACKLIST) + extra_blacklist)
@@ -848,7 +821,7 @@ def process(code):
848821
external_emterpreted_funcs = filter(lambda func: func in tabled_funcs or func in exported_funcs or func in reachable_funcs, emterpreted_funcs)
849822

850823
# process functions, generating bytecode
851-
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)
824+
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)
852825

853826
# load the module and modify it
854827
asm = asm_module.AsmModule(temp)

tools/js-optimizer.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5754,7 +5754,6 @@ function emterpretify(ast) {
57545754
var ASYNC = extraInfo.ASYNC;
57555755
var PROFILING = extraInfo.PROFILING;
57565756
var ASSERTIONS = extraInfo.ASSERTIONS;
5757-
var yieldFuncs = set(extraInfo.yieldFuncs);
57585757

57595758
var RELATIVE_BRANCHES = set('BR', 'BRT', 'BRF');
57605759
var ABSOLUTE_BRANCHES = set('BRA', 'BRTA', 'BRFA');
@@ -5782,6 +5781,14 @@ function emterpretify(ast) {
57825781
return Array.prototype.slice.call(tempUint8, 0, 8);
57835782
}
57845783

5784+
var OK_TO_CALL_WHILE_ASYNC = set('stackSave', 'stackRestore', 'stackAlloc', 'setThrew', '_memset'); // functions which are ok to run while async, even if not emterpreted
5785+
function okToCallWhileAsync(name) {
5786+
// dynCall *can* be on the stack, they are just bridges; what matters is where they go
5787+
if (/^dynCall_/.test(name)) return true;
5788+
if (name in OK_TO_CALL_WHILE_ASYNC) return true;
5789+
return false;
5790+
}
5791+
57855792
function verifyCode(code, stat) {
57865793
if (code.length % 4 !== 0) assert(0, JSON.stringify(code));
57875794
var len = code.length;
@@ -7037,12 +7044,9 @@ function emterpretify(ast) {
70377044

70387045
if (ignore) {
70397046
// we are not emterpreting this function
7040-
if (ASYNC && ASSERTIONS && !/^dynCall_/.test(func[1]) && !(func[1] in yieldFuncs)) {
7047+
if (ASYNC && ASSERTIONS && !okToCallWhileAsync(func[1])) {
70417048
// we need to be careful to never enter non-emterpreted code while doing an async save/restore,
70427049
// which is what happens if non-emterpreted code is on the stack while we attempt to save.
7043-
// note that we special-case dynCall, which *can* be on the stack, they are just bridges; what
7044-
// matters is where they go
7045-
70467050
// add asserts right after each call
70477051
var stack = [];
70487052
traverse(func, function(node, type) {
@@ -7251,10 +7255,6 @@ function emterpretify(ast) {
72517255
});
72527256
if (ASYNC) {
72537257
argStats.push(['if', srcToExp('(asyncState|0) == 1'), srcToStat('asyncState = 3;')]); // we know we are during a sleep, mark the state
7254-
if (ASSERTIONS && !(func[1] in yieldFuncs)) {
7255-
argStats.push(['if', srcToExp('((asyncState|0) == 1) | ((asyncState|0) == 3)'), srcToStat('abort(-12) | 0')]); // if *not* a yield func, we should never get here (trampoline entry)
7256-
// while sleeping (3, or 1 which has not yet been turned into a 3)
7257-
}
72587258
argStats = [['if', srcToExp('(asyncState|0) != 2'), ['block', argStats]]]; // 2 means restore, so do not trample the stack
72597259
}
72607260
func[3] = func[3].concat(argStats);

0 commit comments

Comments
 (0)