diff options
| author | Richard Musiol <mail@richard-musiol.de> | 2018-05-20 00:56:36 +0200 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2018-06-14 21:50:53 +0000 |
| commit | e083dc6307b6593bdd44b219ffd21699d6f17fd7 (patch) | |
| tree | 2a411d82639a778c6aa107529b1d708034c7a7f1 /src/cmd | |
| parent | 5fdacfa89f871888d6f8fde726b8f95f11e674d6 (diff) | |
| download | go-e083dc6307b6593bdd44b219ffd21699d6f17fd7.tar.xz | |
runtime, sycall/js: add support for callbacks from JavaScript
This commit adds support for JavaScript callbacks back into
WebAssembly. This is experimental API, just like the rest of the
syscall/js package. The time package now also uses this mechanism
to properly support timers without resorting to a busy loop.
JavaScript code can call into the same entry point multiple times.
The new RUN register is used to keep track of the program's
run state. Possible values are: starting, running, paused and exited.
If no goroutine is ready any more, the scheduler can put the
program into the "paused" state and the WebAssembly code will
stop running. When a callback occurs, the JavaScript code puts
the callback data into a queue and then calls into WebAssembly
to allow the Go code to continue running.
Updates #18892
Updates #25506
Change-Id: Ib8701cfa0536d10d69bd541c85b0e2a754eb54fb
Reviewed-on: https://go-review.googlesource.com/114197
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/internal/obj/wasm/a.out.go | 3 | ||||
| -rw-r--r-- | src/cmd/internal/obj/wasm/anames.go | 1 | ||||
| -rw-r--r-- | src/cmd/internal/obj/wasm/wasmobj.go | 16 | ||||
| -rw-r--r-- | src/cmd/link/internal/wasm/asm.go | 1 | ||||
| -rw-r--r-- | src/cmd/trace/annotations.go | 4 | ||||
| -rw-r--r-- | src/cmd/trace/annotations_test.go | 6 | ||||
| -rw-r--r-- | src/cmd/trace/trace_test.go | 2 |
7 files changed, 29 insertions, 4 deletions
diff --git a/src/cmd/internal/obj/wasm/a.out.go b/src/cmd/internal/obj/wasm/a.out.go index 9c04be2609..6f882215ff 100644 --- a/src/cmd/internal/obj/wasm/a.out.go +++ b/src/cmd/internal/obj/wasm/a.out.go @@ -219,6 +219,8 @@ const ( // However, it is not allowed to switch goroutines while inside of an ACALLNORESUME call. ACALLNORESUME + ARETUNWIND + AMOVB AMOVH AMOVW @@ -244,6 +246,7 @@ const ( REG_RET1 REG_RET2 REG_RET3 + REG_RUN // locals REG_R0 diff --git a/src/cmd/internal/obj/wasm/anames.go b/src/cmd/internal/obj/wasm/anames.go index 20d04446d0..745f0d773a 100644 --- a/src/cmd/internal/obj/wasm/anames.go +++ b/src/cmd/internal/obj/wasm/anames.go @@ -180,6 +180,7 @@ var Anames = []string{ "F64ReinterpretI64", "RESUMEPOINT", "CALLNORESUME", + "RETUNWIND", "MOVB", "MOVH", "MOVW", diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index ca09b3fa0b..8498b40724 100644 --- a/src/cmd/internal/obj/wasm/wasmobj.go +++ b/src/cmd/internal/obj/wasm/wasmobj.go @@ -25,6 +25,7 @@ var Register = map[string]int16{ "RET1": REG_RET1, "RET2": REG_RET2, "RET3": REG_RET3, + "RUN": REG_RUN, "R0": REG_R0, "R1": REG_R1, @@ -487,7 +488,7 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { p = appendp(p, AEnd) // end of Loop } - case obj.ARET: + case obj.ARET, ARETUNWIND: ret := *p p.As = obj.ANOP @@ -528,7 +529,14 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { p = appendp(p, AI32Add) p = appendp(p, ASet, regAddr(REG_SP)) - // not switching goroutine, return 0 + if ret.As == ARETUNWIND { + // function needs to unwind the WebAssembly stack, return 1 + p = appendp(p, AI32Const, constAddr(1)) + p = appendp(p, AReturn) + break + } + + // not unwinding the WebAssembly stack, return 0 p = appendp(p, AI32Const, constAddr(0)) p = appendp(p, AReturn) } @@ -726,7 +734,7 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { } reg := p.From.Reg switch { - case reg >= REG_PC_F && reg <= REG_RET3: + case reg >= REG_PC_F && reg <= REG_RUN: w.WriteByte(0x23) // get_global writeUleb128(w, uint64(reg-REG_PC_F)) case reg >= REG_R0 && reg <= REG_F15: @@ -743,7 +751,7 @@ func assemble(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { } reg := p.To.Reg switch { - case reg >= REG_PC_F && reg <= REG_RET3: + case reg >= REG_PC_F && reg <= REG_RUN: w.WriteByte(0x24) // set_global writeUleb128(w, uint64(reg-REG_PC_F)) case reg >= REG_R0 && reg <= REG_F15: diff --git a/src/cmd/link/internal/wasm/asm.go b/src/cmd/link/internal/wasm/asm.go index aadb0c3b6e..b7beaa5d2f 100644 --- a/src/cmd/link/internal/wasm/asm.go +++ b/src/cmd/link/internal/wasm/asm.go @@ -304,6 +304,7 @@ func writeGlobalSec(ctxt *ld.Link) { I64, // 6: RET1 I64, // 7: RET2 I64, // 8: RET3 + I32, // 9: RUN } writeUleb128(ctxt.Out, uint64(len(globalRegs))) // number of globals diff --git a/src/cmd/trace/annotations.go b/src/cmd/trace/annotations.go index c91f18ef6f..96c109e0f2 100644 --- a/src/cmd/trace/annotations.go +++ b/src/cmd/trace/annotations.go @@ -1,3 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package main import ( diff --git a/src/cmd/trace/annotations_test.go b/src/cmd/trace/annotations_test.go index 5d2b226b35..a9068d53c1 100644 --- a/src/cmd/trace/annotations_test.go +++ b/src/cmd/trace/annotations_test.go @@ -1,3 +1,9 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !js + package main import ( diff --git a/src/cmd/trace/trace_test.go b/src/cmd/trace/trace_test.go index 852d745b29..9e90f50d4b 100644 --- a/src/cmd/trace/trace_test.go +++ b/src/cmd/trace/trace_test.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build !js + package main import ( |
