-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
co_yield #10991
Comments
Yes, they should. C++ generators are stackless, so all the interesting transformations should happen in the target-independent compiler frontend and we shoudn't need to change anything in the backend or on the Emscripten side. That being said, I don't think we've done any testing with generators. If you run into issues, please file an issue. |
Awesome, thanks Thomas! |
@tlively I'm a beginner on this topic, but I'm wondering. If co_yield currently works within webassembly "as is", could it be used to implement co_await? Wondering if it would be simpler than the binaryen implementation. |
@kripken ^ |
co_await should also "just work" for the same reason as co_yield. Making C++ coroutines interoperate with JS async/await might be a little trickier, though. IIUC, we would need to implement some custom executor that coordinates with JS, but I'm a little fuzzy on the details of what that would look like.
I assume you're thinking about whether Asyncify could be reimplemented with C++ coroutines somehow. It sounds attractive, but unfortunately it would not be a great idea. This is because Asyncify and coroutines are working at different layers of abstraction. In Asyncify, the language is not aware that execution is being paused so it needs to work on unmodified C and C++ code. C++ coroutines, on the other hand, are a language feature that programs have to opt into using via the new keywords in C++20. So in order to implement Asyncify in terms of coroutines, we would have to rewrite the code at some level to use the coroutine features. But even that wouldn't be quite enough because C++ coroutines only save the locals of the current function when it is suspended, but Asyncify needs to save the locals of every function on the stack. So in the end it's actually much simpler to just implement Asyncify as a transformation on the WebAssembly code in Binaryen. |
@tlively
Got it. I can’t find any examples of co_await in webassembly, know of any?
…On Sat, Apr 25, 2020 at 7:26 PM Thomas Lively ***@***.***> wrote:
co_await should also "just work" for the same reason as co_yield. Making
C++ coroutines interoperate with JS async/await might be a little trickier,
though. IIUC, we would need to implement some custom executor that
coordinates with JS, but I'm a little fuzzy on the details of what that
would look like.
Wondering if it would be simpler than the binaryen implementation.
I assume you're thinking about whether Asyncify could be reimplemented
with C++ coroutines somehow. It sounds attractive, but unfortunately it
would not be a great idea. This is because Asyncify and coroutines are
working at different layers of abstraction. In Asyncify, the language is
not aware that execution is being paused so it needs to work on unmodified
C and C++ code. C++ coroutines, on the other hand, are a language feature
that programs have to opt into using via the new keywords in C++20. So in
order to implement Asyncify in terms of coroutines, we would have to
rewrite the code at some level to use the coroutine features. But even that
wouldn't be quite enough because C++ coroutines only save the locals of the
current function when it is suspended, but Asyncify needs to save the
locals of every function on the stack. So in the end it's actually much
simpler to just implement Asyncify as a transformation on the WebAssembly
code in Binaryen.
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#10991 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAEFL7LH6YEJMRVY5GT2DWTRON5S3ANCNFSM4MQGL6WA>
.
|
Starting to realize I may have been confused earlier, see above link. Please correct me if I'm wrong. The binaren coroutine support is more akin to boost fibers? Whereas co_await is really a compiler supported concept? If this is true, I should be able to create a promise implementation, using emscripten, which will support co_await? Like has been done below? https://devblogs.microsoft.com/cppblog/using-ibuv-with-c-resumable-functions/ https://github.com/jimspr/awaituv/blob/master/inc/awaituv.h#L300 |
Yes, that should work just fine, as long as it is not trying to interact with the JS event loop. That kind of integration would be more involved. For the particular example you shared, you would have to port libuv to WebAssembly, too. I'm not sure whether anyone has done that yet. |
I don't need integration w/ JS event loop. This is great! I'll have to start play around with the compiler supported promise/future pattern in libuv, and see if I can get something working in webassembly. |
@tlively @kripken what is @GorNishanov talking about here? I don't understand the tail call part. |
Clang and Emscripten support WebAssembly tail calls with |
@tlively co_await/webassembly, i don't understand, we're saying it will work? or won't work? Or are we just saying it will be inefficient? |
I guess it should work but be inefficient. |
If a compiler, implements symmetric coroutine control transfer using tail calls, not honoring the tail call is a correctness issue. Since without tail calls, a thread stack could be easily exhausted. It a platform does not support tail calls, a different codegen strategy has to be employed. Coroutine parts need to be no longer void, but, return the handle of the next coroutine to be executed and any resumption of the coroutine should be coded as: // in some pseudocode form
void resume(coro$frame* coro)
{
do
{
coro = call actual resume of coro
}
while (coro);
} Clang/llvm relies on musttail to implement symmetric transfer. It will require non-trivial amount of work to implement symmetric transfer without relying on tail calls. |
Need help |
No, what's at issue here is how Clang lowers coroutines and whether or not it tries to use mandatory tail calls. Since WebAssembly tail calls are not enabled by default, my guess is that Clang does not try to use them to lower coroutines. (If it did, that would be a bug). So coroutines should work fine but be slower than they would be if tail calls were enabled. It would be interesting to measure what the performance difference actually is for WebAssembly; it will probably be different than the difference would be on native architectures. |
Has anyone tried using co_await on a chrome canary containing tail call support? |
@GorNishanov could someone at MS test co_await on an Edge browser canary build which supports wasm tail calls? |
With emscripten using clang, should co_yield and generators "just work"?
The text was updated successfully, but these errors were encountered: