mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-18 11:33:59 +00:00
wasm: support //go:wasmexport functions after a call to time.Sleep
This fixes a bug where `//go:wasmexport` functions would not be allowed anymore after a call to `time.Sleep` (when using `-buildmode=default`).
This commit is contained in:
@@ -14,12 +14,13 @@ import (
|
|||||||
// This is the _start entry point, when using -buildmode=default.
|
// This is the _start entry point, when using -buildmode=default.
|
||||||
func wasmEntryCommand() {
|
func wasmEntryCommand() {
|
||||||
// These need to be initialized early so that the heap can be initialized.
|
// These need to be initialized early so that the heap can be initialized.
|
||||||
|
initializeCalled = true
|
||||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||||
wasmExportState = wasmExportStateInMain
|
|
||||||
run()
|
run()
|
||||||
wasmExportState = wasmExportStateExited
|
if mainExited {
|
||||||
beforeExit()
|
beforeExit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the _initialize entry point, when using -buildmode=c-shared.
|
// This is the _initialize entry point, when using -buildmode=c-shared.
|
||||||
@@ -27,6 +28,8 @@ func wasmEntryReactor() {
|
|||||||
// This function is called before any //go:wasmexport functions are called
|
// This function is called before any //go:wasmexport functions are called
|
||||||
// to initialize everything. It must not block.
|
// to initialize everything. It must not block.
|
||||||
|
|
||||||
|
initializeCalled = true
|
||||||
|
|
||||||
// Initialize the heap.
|
// Initialize the heap.
|
||||||
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
|
||||||
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
heapEnd = uintptr(wasm_memory_size(0) * wasmPageSize)
|
||||||
@@ -38,38 +41,23 @@ func wasmEntryReactor() {
|
|||||||
// goroutine.
|
// goroutine.
|
||||||
go func() {
|
go func() {
|
||||||
initAll()
|
initAll()
|
||||||
wasmExportState = wasmExportStateReactor
|
|
||||||
}()
|
}()
|
||||||
scheduler(true)
|
scheduler(true)
|
||||||
if wasmExportState != wasmExportStateReactor {
|
|
||||||
// Unlikely, but if package initializers do something blocking (like
|
|
||||||
// time.Sleep()), that's a bug.
|
|
||||||
runtimePanic("package initializer blocks")
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// There are no goroutines (except for the main one, if you can call it
|
// There are no goroutines (except for the main one, if you can call it
|
||||||
// that), so we can just run all the package initializers.
|
// that), so we can just run all the package initializers.
|
||||||
initAll()
|
initAll()
|
||||||
wasmExportState = wasmExportStateReactor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track which state we're in: before (or during) init, running inside
|
// Whether the runtime was initialized by a call to _initialize or _start.
|
||||||
// main.main, after main.main returned, or reactor mode (after init).
|
var initializeCalled bool
|
||||||
var wasmExportState uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
wasmExportStateInit = iota
|
|
||||||
wasmExportStateInMain
|
|
||||||
wasmExportStateExited
|
|
||||||
wasmExportStateReactor
|
|
||||||
)
|
|
||||||
|
|
||||||
func wasmExportCheckRun() {
|
func wasmExportCheckRun() {
|
||||||
switch wasmExportState {
|
switch {
|
||||||
case wasmExportStateInit:
|
case !initializeCalled:
|
||||||
runtimePanic("//go:wasmexport function called before runtime initialization")
|
runtimePanic("//go:wasmexport function called before runtime initialization")
|
||||||
case wasmExportStateExited:
|
case mainExited:
|
||||||
runtimePanic("//go:wasmexport function called after main.main returned")
|
runtimePanic("//go:wasmexport function called after main.main returned")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const schedulerDebug = false
|
|||||||
// queue a new scheduler invocation using setTimeout.
|
// queue a new scheduler invocation using setTimeout.
|
||||||
const asyncScheduler = GOOS == "js"
|
const asyncScheduler = GOOS == "js"
|
||||||
|
|
||||||
var schedulerDone bool
|
var mainExited bool
|
||||||
|
|
||||||
// Queues used by the scheduler.
|
// Queues used by the scheduler.
|
||||||
var (
|
var (
|
||||||
@@ -166,7 +166,7 @@ func removeTimer(tim *timer) bool {
|
|||||||
func scheduler(returnAtDeadlock bool) {
|
func scheduler(returnAtDeadlock bool) {
|
||||||
// Main scheduler loop.
|
// Main scheduler loop.
|
||||||
var now timeUnit
|
var now timeUnit
|
||||||
for !schedulerDone {
|
for !mainExited {
|
||||||
scheduleLog("")
|
scheduleLog("")
|
||||||
scheduleLog(" schedule")
|
scheduleLog(" schedule")
|
||||||
if sleepQueue != nil || timerQueue != nil {
|
if sleepQueue != nil || timerQueue != nil {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func run() {
|
|||||||
go func() {
|
go func() {
|
||||||
initAll()
|
initAll()
|
||||||
callMain()
|
callMain()
|
||||||
schedulerDone = true
|
mainExited = true
|
||||||
}()
|
}()
|
||||||
scheduler(false)
|
scheduler(false)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+6
@@ -1,5 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
println("called init")
|
println("called init")
|
||||||
}
|
}
|
||||||
@@ -8,6 +10,10 @@ func init() {
|
|||||||
func callTestMain()
|
func callTestMain()
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Check that exported functions can still be called after calling
|
||||||
|
// time.Sleep.
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
|
||||||
// main.main is not used when using -buildmode=c-shared.
|
// main.main is not used when using -buildmode=c-shared.
|
||||||
callTestMain()
|
callTestMain()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user