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

Async await prototype #11501

Open
wants to merge 8 commits into
base: master
from

Conversation

Projects
None yet
7 participants
@lattner
Collaborator

lattner commented Aug 17, 2017

This implements parsing and semantic analysis support for the async/await proposal that @jckarter and I are cooking. It doesn't include SILGen support yet, so it isn't ready for merging.

@LuizZak

This comment has been minimized.

Show comment
Hide comment
@LuizZak

LuizZak Aug 17, 2017

Contributor

Fancy!

Contributor

LuizZak commented Aug 17, 2017

Fancy!

@NachoSoto NachoSoto referenced this pull request Aug 17, 2017

Open

async/await #504

@dcci dcci requested a review from DougGregor Aug 18, 2017

@practicalswift

This comment has been minimized.

Show comment
Hide comment
@practicalswift

practicalswift Aug 18, 2017

Collaborator

Nice stuff! Welcome back! :-)

Collaborator

practicalswift commented Aug 18, 2017

Nice stuff! Welcome back! :-)

@DougGregor

This comment has been minimized.

Show comment
Hide comment
@DougGregor

DougGregor Aug 24, 2017

Member

SIL support for this feature (which is needed for it to do anything) is 10x larger and more complicated than the parsing/sema bits in this pull request, and requires significant design work. Y'all might want to hold on to those party hats.

Member

DougGregor commented Aug 24, 2017

SIL support for this feature (which is needed for it to do anything) is 10x larger and more complicated than the parsing/sema bits in this pull request, and requires significant design work. Y'all might want to hold on to those party hats.

@lattner

This comment has been minimized.

Show comment
Hide comment
@lattner

lattner Aug 24, 2017

Collaborator

One approach does. The other approach builds on the LLVM support for coroutines (which would also allow the llvm inliner etc to work on them).

If you haven't followed the discussions in the c++ community, it is interesting to note that they landed in a very similar design space to the proposed design.

Collaborator

lattner commented Aug 24, 2017

One approach does. The other approach builds on the LLVM support for coroutines (which would also allow the llvm inliner etc to work on them).

If you haven't followed the discussions in the c++ community, it is interesting to note that they landed in a very similar design space to the proposed design.

@jckarter

This comment has been minimized.

Show comment
Hide comment
@jckarter

jckarter Aug 24, 2017

Member

It isn't clear to me how LLVM's coroutine transform can do all the work here without any work at the SIL level. We need to at least be able to generate the destructor edge out of every await point to clean up when all references to a suspended coroutine context get released, and it seems like we'd need a new variation of apply/try_apply with a third edge to represent that. It isn't obvious to me that collecting all those destructor edges and putting them together as the heap object destructor for the coroutine context would just fall out of the llvm-level transform either.

Member

jckarter commented Aug 24, 2017

It isn't clear to me how LLVM's coroutine transform can do all the work here without any work at the SIL level. We need to at least be able to generate the destructor edge out of every await point to clean up when all references to a suspended coroutine context get released, and it seems like we'd need a new variation of apply/try_apply with a third edge to represent that. It isn't obvious to me that collecting all those destructor edges and putting them together as the heap object destructor for the coroutine context would just fall out of the llvm-level transform either.

@lattner

This comment has been minimized.

Show comment
Hide comment
@lattner

lattner Aug 25, 2017

Collaborator

Right, I'm not saying there is zero SILGen work, I'm just saying it is a lot less if you build on the coroutine transformation and optimizations that LLVM does already.

Collaborator

lattner commented Aug 25, 2017

Right, I'm not saying there is zero SILGen work, I'm just saying it is a lot less if you build on the coroutine transformation and optimizations that LLVM does already.

@jckarter

This comment has been minimized.

Show comment
Hide comment
@jckarter

jckarter Aug 25, 2017

Member

Another approach to get to a prototype stage people can play with might be to not do a coroutine transform at all, and just map begin/suspend to the awful brute-force "allocate a callstack and getcontext/setcontext to move on and off the coroutine stack". That wouldn't give you the efficiency or scalability of the real thing, but could at least get the surface semantics to a point people can experiment building things on top of.

Member

jckarter commented Aug 25, 2017

Another approach to get to a prototype stage people can play with might be to not do a coroutine transform at all, and just map begin/suspend to the awful brute-force "allocate a callstack and getcontext/setcontext to move on and off the coroutine stack". That wouldn't give you the efficiency or scalability of the real thing, but could at least get the surface semantics to a point people can experiment building things on top of.

@paulofaria

This comment has been minimized.

Show comment
Hide comment
@paulofaria

paulofaria Sep 21, 2017

Contributor

@jckarter "allocate a callstack and getcontext/setcontext to move on and off the coroutine stack". I'm a bit curious about this topic. This would be similar to Venice coroutines which are built upon libdill coroutines, right? You mentioned before this approach is unsafe for Swift and I believe it even motivated this commit somehow, which marks functions that return twice as unavailable. I know this wouldn't be exactly the same thing because you'd be doing work inside the compiler, so whatever needs to be done to make it safe, you'd do it. I'm just curious about what would have to be done to make this approach safe.

Contributor

paulofaria commented Sep 21, 2017

@jckarter "allocate a callstack and getcontext/setcontext to move on and off the coroutine stack". I'm a bit curious about this topic. This would be similar to Venice coroutines which are built upon libdill coroutines, right? You mentioned before this approach is unsafe for Swift and I believe it even motivated this commit somehow, which marks functions that return twice as unavailable. I know this wouldn't be exactly the same thing because you'd be doing work inside the compiler, so whatever needs to be done to make it safe, you'd do it. I'm just curious about what would have to be done to make this approach safe.

@jckarter

This comment has been minimized.

Show comment
Hide comment
@jckarter

jckarter Sep 21, 2017

Member

Using setjmp/longjmp from Swift is not sound because of the returns_twice semantics of setjmp, and because longjmp unwinds the stack and Swift doesn't emit cleanup information. Suspending and resuming contexts shouldn't have that problem (assuming you're not ever trying to resume the same context twice), though there is framework code out there that will break if the stack pointer is not pointing into the kernel-allocated callstack for the current thread.

Member

jckarter commented Sep 21, 2017

Using setjmp/longjmp from Swift is not sound because of the returns_twice semantics of setjmp, and because longjmp unwinds the stack and Swift doesn't emit cleanup information. Suspending and resuming contexts shouldn't have that problem (assuming you're not ever trying to resume the same context twice), though there is framework code out there that will break if the stack pointer is not pointing into the kernel-allocated callstack for the current thread.

@tanner0101

This comment has been minimized.

Show comment
Hide comment
@tanner0101

tanner0101 Sep 21, 2017

Contributor

Would it be possible to initially implement async/await as simple syntax sugar for callbacks/promises?

Contributor

tanner0101 commented Sep 21, 2017

Would it be possible to initially implement async/await as simple syntax sugar for callbacks/promises?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment