forked from bytecodealliance/wasmtime-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstance.go
More file actions
118 lines (109 loc) · 3.24 KB
/
Copy pathinstance.go
File metadata and controls
118 lines (109 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package wasmtime
// #include <wasmtime.h>
import "C"
import (
"runtime"
"unsafe"
)
// Instance is an instantiated module instance.
// Once a module has been instantiated as an Instance, any exported function can be invoked externally via its function address funcaddr in the store S and an appropriate list val∗ of argument values.
type Instance struct {
_ptr *C.wasm_instance_t
exports map[string]*Extern
freelist *freeList
}
// NewInstance instantiates a WebAssembly `module` with the `imports` provided.
//
// This function will attempt to create a new wasm instance given the provided
// imports. This can fail if the wrong number of imports are specified, the
// imports aren't of the right type, or for other resource-related issues.
//
// This will also run the `start` function of the instance, returning an error
// if it traps.
func NewInstance(store *Store, module *Module, imports []*Extern) (*Instance, error) {
importsRaw := make([]*C.wasm_extern_t, len(imports))
for i, imp := range imports {
importsRaw[i] = imp.ptr()
}
var importsRawPtr **C.wasm_extern_t
if len(imports) > 0 {
importsRawPtr = &importsRaw[0]
}
var trap *C.wasm_trap_t
var ptr *C.wasm_instance_t
err := C.wasmtime_instance_new(
store.ptr(),
module.ptr(),
importsRawPtr,
C.size_t(len(imports)),
&ptr,
&trap,
)
runtime.KeepAlive(store)
runtime.KeepAlive(module)
runtime.KeepAlive(imports)
runtime.KeepAlive(importsRaw)
if err != nil {
return nil, mkError(err)
}
if trap != nil {
return nil, mkTrap(trap)
}
return mkInstance(ptr, store, module), nil
}
func mkInstance(ptr *C.wasm_instance_t, store *Store, module *Module) *Instance {
instance := &Instance{
_ptr: ptr,
exports: make(map[string]*Extern),
freelist: store.freelist,
}
runtime.SetFinalizer(instance, func(instance *Instance) {
freelist := instance.freelist
freelist.lock.Lock()
defer freelist.lock.Unlock()
freelist.instances = append(freelist.instances, instance._ptr)
})
exports := instance.Exports()
for i, ty := range module.Exports() {
instance.exports[ty.Name()] = exports[i]
}
return instance
}
func (i *Instance) ptr() *C.wasm_instance_t {
ret := i._ptr
maybeGC()
return ret
}
type externList struct {
vec C.wasm_extern_vec_t
}
// Exports returns a list of exports from this instance.
//
// Each export is returned as a `*Extern` and lines up with the exports list of
// the associated `Module`.
func (i *Instance) Exports() []*Extern {
externs := &externList{}
C.wasm_instance_exports(i.ptr(), &externs.vec)
runtime.KeepAlive(i)
freelist := i.freelist
runtime.SetFinalizer(externs, func(externs *externList) {
freelist.lock.Lock()
defer freelist.lock.Unlock()
freelist.externVecs = append(freelist.externVecs, &externs.vec)
})
ret := make([]*Extern, int(externs.vec.size))
base := unsafe.Pointer(externs.vec.data)
var ptr *C.wasm_extern_t
for i := 0; i < int(externs.vec.size); i++ {
ptr := *(**C.wasm_extern_t)(unsafe.Pointer(uintptr(base) + unsafe.Sizeof(ptr)*uintptr(i)))
ty := mkExtern(ptr, freelist, externs)
ret[i] = ty
}
return ret
}
// GetExport attempts to find an export on this instance by `name`
//
// May return `nil` if this instance has no export named `name`
func (i *Instance) GetExport(name string) *Extern {
return i.exports[name]
}