mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-15 16:33:40 +00:00
internal/task: use asyncify on webassembly
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.
This commit is contained in:
+30
-18
@@ -18,8 +18,9 @@ import (
|
||||
var flagUpdate = flag.Bool("update", false, "update tests based on test output")
|
||||
|
||||
type testCase struct {
|
||||
file string
|
||||
target string
|
||||
file string
|
||||
target string
|
||||
scheduler string
|
||||
}
|
||||
|
||||
// Basic tests for the compiler. Build some Go files and compare the output with
|
||||
@@ -41,20 +42,21 @@ func TestCompiler(t *testing.T) {
|
||||
}
|
||||
|
||||
tests := []testCase{
|
||||
{"basic.go", ""},
|
||||
{"pointer.go", ""},
|
||||
{"slice.go", ""},
|
||||
{"string.go", ""},
|
||||
{"float.go", ""},
|
||||
{"interface.go", ""},
|
||||
{"func.go", ""},
|
||||
{"pragma.go", ""},
|
||||
{"goroutine.go", "wasm"},
|
||||
{"goroutine.go", "cortex-m-qemu"},
|
||||
{"channel.go", ""},
|
||||
{"intrinsics.go", "cortex-m-qemu"},
|
||||
{"intrinsics.go", "wasm"},
|
||||
{"gc.go", ""},
|
||||
{"basic.go", "", ""},
|
||||
{"pointer.go", "", ""},
|
||||
{"slice.go", "", ""},
|
||||
{"string.go", "", ""},
|
||||
{"float.go", "", ""},
|
||||
{"interface.go", "", ""},
|
||||
{"func.go", "", "coroutines"},
|
||||
{"pragma.go", "", ""},
|
||||
{"goroutine.go", "wasm", "asyncify"},
|
||||
{"goroutine.go", "wasm", "coroutines"},
|
||||
{"goroutine.go", "cortex-m-qemu", "tasks"},
|
||||
{"channel.go", "", ""},
|
||||
{"intrinsics.go", "cortex-m-qemu", ""},
|
||||
{"intrinsics.go", "wasm", ""},
|
||||
{"gc.go", "", ""},
|
||||
}
|
||||
|
||||
_, minor, err := goenv.GetGorootVersion(goenv.Get("GOROOT"))
|
||||
@@ -62,7 +64,7 @@ func TestCompiler(t *testing.T) {
|
||||
t.Fatal("could not read Go version:", err)
|
||||
}
|
||||
if minor >= 17 {
|
||||
tests = append(tests, testCase{"go1.17.go", ""})
|
||||
tests = append(tests, testCase{"go1.17.go", "", ""})
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
@@ -70,7 +72,10 @@ func TestCompiler(t *testing.T) {
|
||||
targetString := "wasm"
|
||||
if tc.target != "" {
|
||||
targetString = tc.target
|
||||
name = tc.file + "-" + tc.target
|
||||
name += "-" + tc.target
|
||||
}
|
||||
if tc.scheduler != "" {
|
||||
name += "-" + tc.scheduler
|
||||
}
|
||||
|
||||
t.Run(name, func(t *testing.T) {
|
||||
@@ -81,6 +86,9 @@ func TestCompiler(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal("failed to load target:", err)
|
||||
}
|
||||
if tc.scheduler != "" {
|
||||
options.Scheduler = tc.scheduler
|
||||
}
|
||||
config := &compileopts.Config{
|
||||
Options: options,
|
||||
Target: target,
|
||||
@@ -94,6 +102,7 @@ func TestCompiler(t *testing.T) {
|
||||
Scheduler: config.Scheduler(),
|
||||
FuncImplementation: config.FuncImplementation(),
|
||||
AutomaticStackSize: config.AutomaticStackSize(),
|
||||
DefaultStackSize: config.Target.DefaultStackSize,
|
||||
}
|
||||
machine, err := NewTargetMachine(compilerConfig)
|
||||
if err != nil {
|
||||
@@ -142,6 +151,9 @@ func TestCompiler(t *testing.T) {
|
||||
if tc.target != "" {
|
||||
outFilePrefix += "-" + tc.target
|
||||
}
|
||||
if tc.scheduler != "" {
|
||||
outFilePrefix += "-" + tc.scheduler
|
||||
}
|
||||
outPath := "./testdata/" + outFilePrefix + ".ll"
|
||||
|
||||
// Update test if needed. Do not check the result.
|
||||
|
||||
Reference in New Issue
Block a user