Skip to content

Remove fastcomp-specific Asyncify code #11868

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 1 addition & 224 deletions src/library_async.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,228 +20,6 @@ mergeInto(LibraryManager.library, {
},

#if ASYNCIFY
#if !WASM_BACKEND
/*
* The layout of normal and async stack frames
*
* --------------------- <-- saved sp for the current function
* <last normal stack frame>
* ---------------------
* pointer to the previous frame <-- __async_cur_frame
* saved sp
* callback function <-- ctx, returned by alloc/reallloc, used by the program
* saved local variable1
* saved local variable2
* ...
* --------------------- <-- STACKTOP
*
*/
__async: 0, // whether a truly async function has been called
__async_unwind: 1, // whether to unwind the async stack frame
__async_retval: '{{{ makeStaticAlloc(2) }}}', // store the return value for async functions
__async_cur_frame: 0, // address to the current frame, which stores previous frame, stack pointer and async context

// __async_retval is not actually required in emscripten_async_resume
// but we want it included when ASYNCIFY is enabled
emscripten_async_resume__deps: ['__async', '__async_unwind', '__async_retval', '__async_cur_frame'],
emscripten_async_resume__sig: 'v',
emscripten_async_resume__asm: true,
emscripten_async_resume: function() {
var callback = 0;
___async = 0;
___async_unwind = 1;
while (1) {
if (!___async_cur_frame) return;
callback = {{{ makeGetValueAsm('___async_cur_frame', 8, 'i32') }}};
// the signature of callback is always vi
// the only argument is ctx
{{{ makeDynCall('vi') }}}(callback | 0, (___async_cur_frame + 8)|0);
if (___async) return; // that was an async call
if (!___async_unwind) {
// keep the async stack
___async_unwind = 1;
continue;
}
// unwind normal stack frame
stackRestore({{{ makeGetValueAsm('___async_cur_frame', 4, 'i32') }}});
// pop the last async stack frame
___async_cur_frame = {{{ makeGetValueAsm('___async_cur_frame', 0, 'i32') }}};
}
},

emscripten_sleep__deps: ['emscripten_async_resume', '$Browser'],
emscripten_sleep: function(ms) {
Module['setAsync'](); // tell the scheduler that we have a callback on hold
Browser.safeSetTimeout(_emscripten_async_resume, ms);
},

emscripten_alloc_async_context__deps: ['__async_cur_frame'],
emscripten_alloc_async_context__sig: 'iii',
emscripten_alloc_async_context__asm: true,
emscripten_alloc_async_context: function(len, sp) {
len = len|0;
sp = sp|0;
// len is the size of ctx
// we also need to store prev_frame, stack pointer before ctx
var new_frame = 0; new_frame = stackAlloc((len + 8)|0)|0;
// save sp
{{{ makeSetValueAsm('new_frame', 4, 'sp', 'i32') }}};
// link the frame with previous one
{{{ makeSetValueAsm('new_frame', 0, '___async_cur_frame', 'i32') }}};
___async_cur_frame = new_frame;
return (___async_cur_frame + 8)|0;
},

emscripten_realloc_async_context__deps: ['__async_cur_frame'],
emscripten_realloc_async_context__sig: 'ii',
emscripten_realloc_async_context__asm: true,
emscripten_realloc_async_context: function(len) {
len = len|0;
// assuming that we have on the stacktop
stackRestore(___async_cur_frame | 0);
return ((stackAlloc((len + 8)|0)|0) + 8)|0;
},

emscripten_free_async_context__deps: ['__async_cur_frame'],
emscripten_free_async_context__sig: 'vi',
emscripten_free_async_context__asm: true,
emscripten_free_async_context: function(ctx) {
// this function is called when a possibly async function turned out to be sync
// just undo a recent emscripten_alloc_async_context
ctx = ctx|0;
#if ASSERTIONS
if ((((___async_cur_frame + 8)|0) != (ctx|0))|0) abort();
#endif
stackRestore(___async_cur_frame | 0);
___async_cur_frame = {{{ makeGetValueAsm('___async_cur_frame', 0, 'i32') }}};
},

emscripten_check_async: true,
emscripten_do_not_unwind: true,
emscripten_do_not_unwind_async: true,

emscripten_get_async_return_value_addr__deps: ['__async_retval'],
emscripten_get_async_return_value_addr: true,

/*
* Layout of an ASYNCIFY coroutine structure
*
* 0 callee's async ctx
* 4 callee's STACKTOP
* 8 callee's STACK_MAX
* 12 my async ctx
* 16 my STACKTOP
* 20 my stack size
* 24 coroutine function
* 28 coroutine arg
* 32 my stack:
* ...
*/
emscripten_coroutine_create__sig: 'iiii',
emscripten_coroutine_create__asm: true,
emscripten_coroutine_create__deps: ['malloc', 'emscripten_alloc_async_context'],
emscripten_coroutine_create: function(f, arg, stack_size) {
f = f|0;
arg = arg|0;
stack_size = stack_size|0;
var coroutine = 0;

if ((stack_size|0) <= 0) stack_size = 4096;

coroutine = _malloc(stack_size + 32 | 0) | 0;
{{{ makeSetValueAsm('coroutine', 12, 0, 'i32') }}};
{{{ makeSetValueAsm('coroutine', 16, '(coroutine+32)', 'i32') }}};
{{{ makeSetValueAsm('coroutine', 20, 'stack_size', 'i32') }}};
{{{ makeSetValueAsm('coroutine', 24, 'f', 'i32') }}};
{{{ makeSetValueAsm('coroutine', 28, 'arg', 'i32') }}};
return coroutine|0;
},
emscripten_coroutine_next__sig: 'ii',
emscripten_coroutine_next__asm: true,
emscripten_coroutine_next__deps: ['__async_cur_frame', '__async', 'emscripten_async_resume', 'free'],
emscripten_coroutine_next: function(coroutine) {
coroutine = coroutine|0;
var coroutine_not_finished = 0, temp = 0;
// switch context
{{{ makeSetValueAsm('coroutine', 0, '___async_cur_frame', 'i32') }}};
temp = stackSave() | 0;
{{{ makeSetValueAsm('coroutine', 4, 'temp', 'i32') }}};
{{{ makeSetValueAsm('coroutine', 8, 'STACK_MAX', 'i32') }}};
___async_cur_frame = {{{ makeGetValueAsm('coroutine', 12, 'i32') }}};
stackRestore({{{ makeGetValueAsm('coroutine', 16, 'i32') }}});
STACK_MAX = coroutine + 32 + {{{ makeGetValueAsm('coroutine', 20, 'i32') }}} | 0;

if (!___async_cur_frame) {
// first run
{{{ makeDynCall('vi') }}}(
{{{ makeGetValueAsm('coroutine', 24, 'i32') }}},
{{{ makeGetValueAsm('coroutine', 28, 'i32') }}}
);
} else {
_emscripten_async_resume();
}

// switch context
{{{ makeSetValueAsm('coroutine', 12, '___async_cur_frame', 'i32') }}};
temp = stackSave() | 0;
{{{ makeSetValueAsm('coroutine', 16, 'temp', 'i32') }}};
___async_cur_frame = {{{ makeGetValueAsm('coroutine', 0, 'i32') }}};
stackRestore({{{ makeGetValueAsm('coroutine', 4, 'i32') }}});
STACK_MAX = {{{ makeGetValueAsm('coroutine', 8, 'i32') }}};

coroutine_not_finished = ___async;
if (!coroutine_not_finished) {
// coroutine has finished
_free(coroutine);
}
// coroutine may be created during an async function
// we do not want to affect the original async ctx
// strictly we should backup and restore ___async, ___async_retval and ___async_unwind
// but ___async=0 seems enough
___async = 0;

return coroutine_not_finished|0;
},
emscripten_yield__sig: 'v',
emscripten_yield__asm: true,
emscripten_yield: function() {
___async = 1;
},

emscripten_wget__deps: ['emscripten_async_resume', '$PATH_FS', '$Browser'],
emscripten_wget: function(url, file) {
var _url = UTF8ToString(url);
var _file = UTF8ToString(file);
_file = PATH_FS.resolve(FS.cwd(), _file);
Module['setAsync']();
noExitRuntime = true;
var destinationDirectory = PATH.dirname(_file);
FS.createPreloadedFile(
destinationDirectory,
PATH.basename(_file),
_url, true, true,
_emscripten_async_resume,
_emscripten_async_resume,
undefined, // dontCreateFile
undefined, // canOwn
function() { // preFinish
// if the destination directory does not yet exist, create it
FS.mkdirTree(destinationDirectory);
}
);
},

emscripten_fiber_init: function() {
throw 'emscripten_fiber_init is not implemented for fastcomp ASYNCIFY';
},
emscripten_fiber_init_from_current_context: function() {
throw 'emscripten_fiber_init_from_current_context is not implemented for fastcomp ASYNCIFY';
},
emscripten_fiber_swap: function() {
throw 'emscripten_fiber_swap is not implemented for fastcomp ASYNCIFY';
},

#else // !WASM_BACKEND
$Asyncify__deps: ['$Browser', '$runAndAbortIfError'],
$Asyncify: {
State: {
Expand Down Expand Up @@ -719,7 +497,6 @@ mergeInto(LibraryManager.library, {
emscripten_yield: function() {
throw 'emscripten_yield has been removed. Please use the Fibers API';
},
#endif
#else // ASYNCIFY
emscripten_sleep: function() {
throw 'Please compile your program with async support in order to use asynchronous operations like emscripten_sleep';
Expand Down Expand Up @@ -754,6 +531,6 @@ mergeInto(LibraryManager.library, {
#endif // ASYNCIFY
});

if (WASM_BACKEND && ASYNCIFY) {
if (ASYNCIFY) {
DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push('$Asyncify');
}
4 changes: 2 additions & 2 deletions src/library_idbstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ var LibraryIDBStore = {
});
},

#if WASM_BACKEND && ASYNCIFY
#if ASYNCIFY
emscripten_idb_load: function(db, id, pbuffer, pnum, perror) {
Asyncify.handleSleep(function(wakeUp) {
IDBStore.getFile(UTF8ToString(db), UTF8ToString(id), function(error, byteArray) {
Expand Down Expand Up @@ -166,7 +166,7 @@ var LibraryIDBStore = {
emscripten_idb_exists: function() {
throw 'Please compile your program with async support in order to use synchronous operations like emscripten_idb_exists, etc.';
},
#endif // WASM_BACKEND && ASYNCIFY
#endif // ASYNCIFY
};

autoAddDeps(LibraryIDBStore, '$IDBStore');
Expand Down
4 changes: 2 additions & 2 deletions src/library_sdl.js
Original file line number Diff line number Diff line change
Expand Up @@ -1730,7 +1730,7 @@ var LibrarySDL = {
// We actually do the whole screen in Unlock...
},

#if !(WASM_BACKEND && ASYNCIFY)
#if !ASYNCIFY
SDL_Delay: function(delay) {
if (!ENVIRONMENT_IS_WORKER) abort('SDL_Delay called on the main thread! Potential infinite loop, quitting. (consider building with async support like ASYNCIFY)');
// horrible busy-wait, but in a worker it at least does not block rendering
Expand Down Expand Up @@ -2504,7 +2504,7 @@ var LibrarySDL = {
}
}

#if (ASYNCIFY && WASM_BACKEND)
#if ASYNCIFY
var sleepCallback = function() {
if (SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData();
};
Expand Down
4 changes: 2 additions & 2 deletions src/library_syscall.js
Original file line number Diff line number Diff line change
Expand Up @@ -1565,7 +1565,7 @@ var SyscallsLibrary = {
fd_sync__sig: 'ii',
fd_sync: function(fd) {
var stream = SYSCALLS.getStreamFromFD(fd);
#if WASM_BACKEND && ASYNCIFY
#if ASYNCIFY
return Asyncify.handleSleep(function(wakeUp) {
var mount = stream.node.mount;
if (!mount.type.syncfs) {
Expand All @@ -1586,7 +1586,7 @@ var SyscallsLibrary = {
return -stream.stream_ops.fsync(stream);
}
return 0; // we can't do anything synchronously; the in-memory FS is already synced to
#endif // WASM_BACKEND && ASYNCIFY
#endif // ASYNCIFY
},

#if !WASM_BACKEND
Expand Down
8 changes: 4 additions & 4 deletions src/postamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,16 @@ function callMain(args) {
// In PROXY_TO_PTHREAD builds, we should never exit the runtime below, as execution is asynchronously handed
// off to a pthread.
#if !PROXY_TO_PTHREAD
#if WASM_BACKEND && ASYNCIFY
#if ASYNCIFY
// if we are saving the stack, then do not call exit, we are not
// really exiting now, just unwinding the JS stack
if (!noExitRuntime) {
#endif // WASM_BACKEND && ASYNCIFY
#endif // ASYNCIFY
// if we're not running an evented main loop, it's time to exit
exit(ret, /* implicit = */ true);
#if WASM_BACKEND && ASYNCIFY
#if ASYNCIFY
}
#endif // WASM_BACKEND && ASYNCIFY
#endif // ASYNCIFY
}
catch(e) {
if (e instanceof ExitStatus) {
Expand Down
8 changes: 4 additions & 4 deletions src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ function ccall(ident, returnType, argTypes, args, opts) {
}
}
var ret = func.apply(null, cArgs);
#if ASYNCIFY && WASM_BACKEND
#if ASYNCIFY
var asyncMode = opts && opts.async;
var runningAsync = typeof Asyncify === 'object' && Asyncify.currData;
var prevRunningAsync = typeof Asyncify === 'object' && Asyncify.asyncFinalizers.length > 0;
Expand All @@ -163,7 +163,7 @@ function ccall(ident, returnType, argTypes, args, opts) {

ret = convertReturnValue(ret);
if (stack !== 0) stackRestore(stack);
#if ASYNCIFY && WASM_BACKEND
#if ASYNCIFY
// If this is an async ccall, ensure we return a promise
if (opts && opts.async) return Promise.resolve(ret);
#endif
Expand Down Expand Up @@ -910,7 +910,7 @@ function createWasm() {
#if RELOCATABLE
exports = relocateExports(exports, GLOBAL_BASE, 0);
#endif
#if WASM_BACKEND && ASYNCIFY
#if ASYNCIFY
exports = Asyncify.instrumentWasmExports(exports);
#endif
Module['asm'] = exports;
Expand Down Expand Up @@ -1126,7 +1126,7 @@ function createWasm() {
if (Module['instantiateWasm']) {
try {
var exports = Module['instantiateWasm'](info, receiveInstance);
#if WASM_BACKEND && ASYNCIFY
#if ASYNCIFY
exports = Asyncify.instrumentWasmExports(exports);
#endif
return exports;
Expand Down