Skip to content

Commit e5faee2

Browse files
committed
Bind new support for tables
Binds functions added in bytecodealliance/wasmtime#1654 Closes #5
1 parent 55cf565 commit e5faee2

File tree

2 files changed

+175
-2
lines changed

2 files changed

+175
-2
lines changed

table.go

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,38 @@
11
package wasmtime
22

3-
// #include <wasm.h>
3+
// #include <wasmtime.h>
44
import "C"
5-
import "runtime"
5+
import (
6+
"errors"
7+
"runtime"
8+
)
69

710
type Table struct {
811
_ptr *C.wasm_table_t
912
_owner interface{}
1013
freelist *freeList
1114
}
1215

16+
// Creates a new `Table` in the given `Store` with the specified `ty`.
17+
//
18+
// The `ty` must be a `funcref` table and `init` is the initial value for all
19+
// table slots, and is allowed to be `nil`.
20+
func NewTable(store *Store, ty *TableType, init *Func) (*Table, error) {
21+
var init_ptr *C.wasm_func_t
22+
if init != nil {
23+
init_ptr = init.ptr()
24+
}
25+
var ptr *C.wasm_table_t
26+
err := C.wasmtime_funcref_table_new(store.ptr(), ty.ptr(), init_ptr, &ptr)
27+
runtime.KeepAlive(store)
28+
runtime.KeepAlive(ty)
29+
runtime.KeepAlive(init)
30+
if err != nil {
31+
return nil, mkError(err)
32+
}
33+
return mkTable(ptr, store.freelist, nil), nil
34+
}
35+
1336
func mkTable(ptr *C.wasm_table_t, freelist *freeList, owner interface{}) *Table {
1437
f := &Table{_ptr: ptr, _owner: owner, freelist: freelist}
1538
if owner == nil {
@@ -35,12 +58,74 @@ func (t *Table) owner() interface{} {
3558
return t
3659
}
3760

61+
// Returns the size of this table in units of elements.
3862
func (t *Table) Size() uint32 {
3963
ret := C.wasm_table_size(t.ptr())
4064
runtime.KeepAlive(t)
4165
return uint32(ret)
4266
}
4367

68+
// Grows this funcref table by the number of units specified, using the
69+
// specified initializer value for new slots.
70+
//
71+
// Note that `init` is allowed to be `nil`.
72+
//
73+
// Returns an error if the table failed to grow, or the previous size of the
74+
// table if growth was successful.
75+
func (t *Table) Grow(delta uint32, init *Func) (uint32, error) {
76+
var init_ptr *C.wasm_func_t
77+
if init != nil {
78+
init_ptr = init.ptr()
79+
}
80+
var prev C.uint32_t
81+
err := C.wasmtime_funcref_table_grow(t.ptr(), C.uint32_t(delta), init_ptr, &prev)
82+
runtime.KeepAlive(t)
83+
runtime.KeepAlive(init)
84+
if err == nil {
85+
return uint32(prev), nil
86+
} else {
87+
return 0, mkError(err)
88+
}
89+
}
90+
91+
// Gets an item from this table from the specified index.
92+
//
93+
// Returns an error if the index is out of bounds, or returns a function (which
94+
// may be `nil`) if the index is in bounds corresponding to the entry at the
95+
// specified index.
96+
func (t *Table) Get(idx uint32) (*Func, error) {
97+
var func_ptr *C.wasm_func_t
98+
ok := C.wasmtime_funcref_table_get(t.ptr(), C.uint32_t(idx), &func_ptr)
99+
runtime.KeepAlive(t)
100+
if ok {
101+
if func_ptr == nil {
102+
return nil, nil
103+
}
104+
return mkFunc(func_ptr, t.freelist, nil), nil
105+
} else {
106+
return nil, errors.New("index out of bounds")
107+
}
108+
}
109+
110+
// Sets an item in this table at the specified index.
111+
//
112+
// Returns an error if the index is out of bounds.
113+
func (t *Table) Set(idx uint32, val *Func) error {
114+
var func_ptr *C.wasm_func_t
115+
if val != nil {
116+
func_ptr = val.ptr()
117+
}
118+
err := C.wasmtime_funcref_table_set(t.ptr(), C.uint32_t(idx), func_ptr)
119+
runtime.KeepAlive(t)
120+
runtime.KeepAlive(val)
121+
if err == nil {
122+
return nil
123+
} else {
124+
return mkError(err)
125+
}
126+
}
127+
128+
// Returns the underlying type of this table
44129
func (t *Table) Type() *TableType {
45130
ptr := C.wasm_table_type(t.ptr())
46131
runtime.KeepAlive(t)

table_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package wasmtime
2+
3+
import "testing"
4+
5+
func TestTable(t *testing.T) {
6+
store := NewStore(NewEngine())
7+
ty := NewTableType(NewValType(KindFuncref), Limits{Min: 1, Max: 3})
8+
table, err := NewTable(store, ty, nil)
9+
if err != nil {
10+
panic(err)
11+
}
12+
if table.Size() != 1 {
13+
panic("wrong size")
14+
}
15+
16+
f, err := table.Get(0)
17+
if err != nil {
18+
panic(err)
19+
}
20+
if f != nil {
21+
panic("expected nil")
22+
}
23+
f, err = table.Get(1)
24+
if err == nil {
25+
panic("expected error")
26+
}
27+
if f != nil {
28+
panic("expected nil")
29+
}
30+
31+
err = table.Set(0, nil)
32+
if err != nil {
33+
panic(err)
34+
}
35+
err = table.Set(1, nil)
36+
if err == nil {
37+
panic("expected error")
38+
}
39+
err = table.Set(0, WrapFunc(store, func() {}))
40+
if err != nil {
41+
panic(nil)
42+
}
43+
f, err = table.Get(0)
44+
if err != nil {
45+
panic(err)
46+
}
47+
if f == nil {
48+
panic("expected not nil")
49+
}
50+
51+
prev_size, err := table.Grow(1, nil)
52+
if err != nil {
53+
panic(err)
54+
}
55+
if prev_size != 1 {
56+
print(prev_size)
57+
panic("bad prev")
58+
}
59+
f, err = table.Get(1)
60+
if err != nil {
61+
panic(err)
62+
}
63+
if f != nil {
64+
panic("expected nil")
65+
}
66+
67+
called := false
68+
_, err = table.Grow(1, WrapFunc(store, func() {
69+
called = true
70+
}))
71+
if err != nil {
72+
panic(err)
73+
}
74+
f, err = table.Get(2)
75+
if err != nil {
76+
panic(err)
77+
}
78+
if called {
79+
panic("called already?")
80+
}
81+
_, err = f.Call()
82+
if err != nil {
83+
panic(err)
84+
}
85+
if !called {
86+
panic("should have called")
87+
}
88+
}

0 commit comments

Comments
 (0)