mirror of
https://codeberg.org/superseriousbusiness/gotosocial.git
synced 2024-12-27 19:38:26 +03:00
75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
|
package wasm
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
|
||
|
"github.com/tetratelabs/wazero/api"
|
||
|
"github.com/tetratelabs/wazero/experimental"
|
||
|
)
|
||
|
|
||
|
type snapshotskey struct{}
|
||
|
|
||
|
// withSetjmpLongjmp updates the context to contain wazero/experimental.Snapshotter{} support,
|
||
|
// and embeds the necessary snapshots map required for later calls to Setjmp() / Longjmp().
|
||
|
func withSetjmpLongjmp(ctx context.Context) context.Context {
|
||
|
snapshots := make(map[uint32]experimental.Snapshot, 10)
|
||
|
ctx = experimental.WithSnapshotter(ctx)
|
||
|
ctx = context.WithValue(ctx, snapshotskey{}, snapshots)
|
||
|
return ctx
|
||
|
}
|
||
|
|
||
|
func getSnapshots(ctx context.Context) map[uint32]experimental.Snapshot {
|
||
|
v, _ := ctx.Value(snapshotskey{}).(map[uint32]experimental.Snapshot)
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
// setjmp implements the C function: setjmp(env jmp_buf)
|
||
|
func setjmp(ctx context.Context, mod api.Module, stack []uint64) {
|
||
|
|
||
|
// Input arguments.
|
||
|
envptr := api.DecodeU32(stack[0])
|
||
|
|
||
|
// Take snapshot of current execution environment.
|
||
|
snapshotter := experimental.GetSnapshotter(ctx)
|
||
|
snapshot := snapshotter.Snapshot()
|
||
|
|
||
|
// Get stored snapshots map.
|
||
|
snapshots := getSnapshots(ctx)
|
||
|
if snapshots == nil {
|
||
|
panic("setjmp / longjmp not supported")
|
||
|
}
|
||
|
|
||
|
// Set latest snapshot in map.
|
||
|
snapshots[envptr] = snapshot
|
||
|
|
||
|
// Set return.
|
||
|
stack[0] = 0
|
||
|
}
|
||
|
|
||
|
// longjmp implements the C function: int longjmp(env jmp_buf, value int)
|
||
|
func longjmp(ctx context.Context, mod api.Module, stack []uint64) {
|
||
|
|
||
|
// Input arguments.
|
||
|
envptr := api.DecodeU32(stack[0])
|
||
|
// val := stack[1]
|
||
|
|
||
|
// Get stored snapshots map.
|
||
|
snapshots := getSnapshots(ctx)
|
||
|
if snapshots == nil {
|
||
|
panic("setjmp / longjmp not supported")
|
||
|
}
|
||
|
|
||
|
// Get snapshot stored in map.
|
||
|
snapshot := snapshots[envptr]
|
||
|
if snapshot == nil {
|
||
|
panic("must first call setjmp")
|
||
|
}
|
||
|
|
||
|
// Set return.
|
||
|
stack[0] = 0
|
||
|
|
||
|
// Restore execution and
|
||
|
// return passed value arg.
|
||
|
snapshot.Restore(stack[1:])
|
||
|
}
|