Skip to content

Commit

Permalink
Remove fastcomp-specific Asyncify code (#11868)
Browse files Browse the repository at this point in the history
See #11860
  • Loading branch information
Akaricchi authored Aug 12, 2020
1 parent aa130a4 commit 9b5c5b9
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 238 deletions.
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 @@ -220,16 +220,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 @@ -906,7 +906,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 @@ -1122,7 +1122,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

0 comments on commit 9b5c5b9

Please sign in to comment.