aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorRichard Musiol <mail@richard-musiol.de>2018-05-20 00:56:36 +0200
committerAustin Clements <austin@google.com>2018-06-14 21:50:53 +0000
commite083dc6307b6593bdd44b219ffd21699d6f17fd7 (patch)
tree2a411d82639a778c6aa107529b1d708034c7a7f1 /src/cmd
parent5fdacfa89f871888d6f8fde726b8f95f11e674d6 (diff)
downloadgo-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.go3
-rw-r--r--src/cmd/internal/obj/wasm/anames.go1
-rw-r--r--src/cmd/internal/obj/wasm/wasmobj.go16
-rw-r--r--src/cmd/link/internal/wasm/asm.go1
-rw-r--r--src/cmd/trace/annotations.go4
-rw-r--r--src/cmd/trace/annotations_test.go6
-rw-r--r--src/cmd/trace/trace_test.go2
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 (