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
internal/task: use asyncify on WASM #2011
Conversation
What work is remaining to get this PR finished? I'd love to help out any way I can. |
This is mainly blocked by #2035 I think |
While that bug is getting fixed, is there work that could be done on this issue even with having to run wasm-opt manually? |
I'm almost inclined to say that we should perhaps just get this finished (even without #2035). That means compiling for WebAssembly requires an extra binary - but I think that's only required when using the new Asincify based scheduler? Thoughts? |
Alright, I can modify this to just shell out to wasm-opt for now when using asyncify. |
I made that change and attempted to debug some issues. It appears that after the initial launch suspend, resumed goroutines will not suspend again. I don't quite understand it yet. |
I'll take a look at this on Monday and see what I can come up with. |
I have fixed what was probably the biggest bug. However, there are still some things left to be fixed apparently, such as weird WASI crashes and some sort of unicode error in the reflect test (. . . and i still havent added binaryen to CI). |
\o/. This works great on my little test
However, I'm getting an unaligned pointer error with I managed to fix it with this patch.
It seems like a proper fix lies elsewhere, although I'm not sure where.. Trying to run the above ping-pong code with
I'm still looking into this.. |
I suspect this may be fixed by #2009. This PR is kinda old so I can rebase tommorow. |
Adding
gives me a much better error:
So indeed, something about asyncify is futzing with the alignment of the pointers and making things unhappy. |
I rebased my local copy against |
Patching gc_leaking.go with
allows both gc=conservative and gc=leaking to run the pingpong example. |
For some reason I thought chocolatey had binaryen. I guess I will need to switch over the install then. |
Something about the asyncify code is causing #2172 to fail |
src/internal/task/task_asyncify.go
Outdated
s.args = args | ||
|
||
// Create a stack. | ||
stackSize = align(stackSize) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Normally, I would expect an aligned stack to be passed in. For example, a stack size of 2048 is very much aligned.
I never really thought about aligning it, but yeah, technically it might need to be aligned.
I don't think this needs to be done at runtime (although there is a good chance it's optimized away in this case): it's only ever specified in code (in compileopts/target.go for example) or in target JSON files. The only way to easily change it is by modifying the JSON file directly, for example. If we're going to align it, I think it would be better to do it at compile time instead of at runtime, for example here:
Line 125 in 1573826
stackSize = llvm.ConstInt(b.uintptrType, b.DefaultStackSize, false) |
This can be done by aligning to 16 bytes, I believe that's nowadays a pretty standard alignment (even on riscv32 and i386, for example).
|
I have created a fix for the WASM scheduler recursion failure: #2178 |
I think this branch still has an odd failure. Trying to build the following program with
produces the following build failure:
|
I have been poking around, and it currently appears that the interface lowering pass is the first pass introducing type errors when building that code. |
I identified the issue and seperated it into #2197 |
Hmm, it looks like LLVM 10 may have issues with the not-yet-resolved symbols for asyncify. I am not really sure how we want to handle this. I guess we could disable this on LLVM 10? I am not sure of a better option. |
Given that llvm 13 is out now, how many versions behind is tinygo committed to supporting? |
Don't let that be a blocker. If LLVM 10 is an issue, we'll drop LLVM 10 support. That's a really old version by now. (Usually we support the last two LLVM versions or so, to make things easier for distributions). Even more so because this PR is a blocker to add support for newer LLVM versions. |
It looks like the version of GCC used by Debian Stretch is too old to build |
I managed to work around that by using the copy of clang that we build. |
If my debugging attempts are correct, it looks like binaryen is still trying to dynamically link against
|
For the TinyGo build I use |
Yeah I just realized that. Adding now. |
I can try rebooting to Windows to test some build options, would that help? |
I suspect that I just fixed it. If not, I finally have a Windows VM setup so I can test there. |
All tests are now passing. |
This change implements a new "scheduler" for WebAssembly using binaryen's asyncify transform. This is more reliable than the current "coroutines" transform, and works with non-Go code in the call stack. runtime (js/wasm): handle scheduler nesting If WASM calls into JS which calls back into WASM, it is possible for the scheduler to nest. The event from the callback must be handled immediately, so the task cannot simply be deferred to the outer scheduler. This creates a minimal scheduler loop which is used to handle such nesting.
I did a quick squash/cleanup, so I think this is ready for a final review. |
Do we need to modify the dev Dockerfile if you want to use this scheduler? https://github.com/tinygo-org/tinygo/blob/dev/Dockerfile#L23-L28 |
Oops I forgot to install cmake and ninja.
@aykevl any last comments before merge? |
Is this the fix to get WASM compilation working again ? |
WASM compilation is working afaik. This PR is to add asyncify as an option for task scheduling for WASM programs. |
ok thank for the response. #1972 is blocking one . I believe is for gio when building to Web ( wasm ). I need to try again... |
default: | ||
return "" | ||
} | ||
} | ||
|
||
// Find wasm-opt, or exit with an error. | ||
func findWasmOpt() string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[this comment was intended to be part of the review but I forgot to click the "start review" button]
I think this function can be simplified. In short: the bundled wasm-opt binaries don't need to be checked for a version.
I would suggest the following logic:
if $TINYGOROOT/bin/wasm-opt[.exe] exists:
return this path
if $TINYGOROOT/build/wasm-opt[.exe] exists:
return this path
look for wasm-opt using LookPath
if not found:
print or return error
check for version
if version too old:
return error
return this path
This is not a blocker to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should still be doing a version check regardless for now, until we can actually link it in properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has already caught one issue, so it is still helpful.
The Dockerfile issues have been fixed. |
OK merge time! Great work on this @niaow thank you. Also thanks to everyone who helped review/test. |
This currently requires manually running the compiled wasm through
wasm-opt
.Very little works so far.
Issue: #1101