1use wasmer_types::TableType;
2
3use crate::{
4 AsStoreMut, AsStoreRef, ExportError, Exportable, Extern, StoreMut, StoreRef, Value,
5 error::RuntimeError,
6 macros::backend::{gen_rt_ty, match_rt},
7 store::BackendStore,
8 vm::{VMExtern, VMExternTable},
9};
10gen_rt_ty! {
20 #[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
21 #[derive(Debug, Clone, PartialEq, Eq, derive_more::From)]
22 pub BackendTable(entities::table::Table);
23}
24
25impl BackendTable {
26 #[inline]
32 pub fn new(
33 store: &mut impl AsStoreMut,
34 ty: TableType,
35 init: Value,
36 ) -> Result<Self, RuntimeError> {
37 match &store.as_store_mut().inner.store {
38 #[cfg(feature = "sys")]
39 BackendStore::Sys(_) => Ok(Self::Sys(
40 crate::backend::sys::entities::table::Table::new(store, ty, init)?,
41 )),
42 #[cfg(feature = "wamr")]
43 BackendStore::Wamr(_) => Ok(Self::Wamr(
44 crate::backend::wamr::entities::table::Table::new(store, ty, init)?,
45 )),
46 #[cfg(feature = "wasmi")]
47 BackendStore::Wasmi(_) => Ok(Self::Wasmi(
48 crate::backend::wasmi::entities::table::Table::new(store, ty, init)?,
49 )),
50 #[cfg(feature = "v8")]
51 BackendStore::V8(_) => Ok(Self::V8(crate::backend::v8::entities::table::Table::new(
52 store, ty, init,
53 )?)),
54 #[cfg(feature = "js")]
55 BackendStore::Js(_) => Ok(Self::Js(crate::backend::js::entities::table::Table::new(
56 store, ty, init,
57 )?)),
58 #[cfg(feature = "jsc")]
59 BackendStore::Jsc(_) => Ok(Self::Jsc(
60 crate::backend::jsc::entities::table::Table::new(store, ty, init)?,
61 )),
62 }
63 }
64
65 #[inline]
67 pub fn ty(&self, store: &impl AsStoreRef) -> TableType {
68 match_rt!(on self => s {
69 s.ty(store)
70 })
71 }
72
73 #[inline]
75 pub fn get(&self, store: &mut impl AsStoreMut, index: u32) -> Option<Value> {
76 match_rt!(on self => s {
77 s.get(store, index)
78 })
79 }
80
81 #[inline]
83 pub fn set(
84 &self,
85 store: &mut impl AsStoreMut,
86 index: u32,
87 val: Value,
88 ) -> Result<(), RuntimeError> {
89 match_rt!(on self => s {
90 s.set(store, index, val)
91 })
92 }
93
94 #[inline]
96 pub fn size(&self, store: &impl AsStoreRef) -> u32 {
97 match_rt!(on self => s {
98 s.size(store)
99 })
100 }
101
102 #[inline]
112 pub fn grow(
113 &self,
114 store: &mut impl AsStoreMut,
115 delta: u32,
116 init: Value,
117 ) -> Result<u32, RuntimeError> {
118 match_rt!(on self => s {
119 s.grow(store, delta, init)
120 })
121 }
122
123 #[inline]
131 pub fn copy(
132 store: &mut impl AsStoreMut,
133 dst_table: &Self,
134 dst_index: u32,
135 src_table: &Self,
136 src_index: u32,
137 len: u32,
138 ) -> Result<(), RuntimeError> {
139 match &store.as_store_mut().inner.store {
140 #[cfg(feature = "sys")]
141 BackendStore::Sys(_) => crate::backend::sys::entities::table::Table::copy(
142 store,
143 dst_table.as_sys(),
144 dst_index,
145 src_table.as_sys(),
146 src_index,
147 len,
148 ),
149 #[cfg(feature = "wamr")]
150 BackendStore::Wamr(_) => crate::backend::wamr::entities::table::Table::copy(
151 store,
152 dst_table.as_wamr(),
153 dst_index,
154 src_table.as_wamr(),
155 src_index,
156 len,
157 ),
158 #[cfg(feature = "wasmi")]
159 BackendStore::Wasmi(_) => crate::backend::wasmi::entities::table::Table::copy(
160 store,
161 dst_table.as_wasmi(),
162 dst_index,
163 src_table.as_wasmi(),
164 src_index,
165 len,
166 ),
167
168 #[cfg(feature = "v8")]
169 BackendStore::V8(_) => crate::backend::v8::entities::table::Table::copy(
170 store,
171 dst_table.as_v8(),
172 dst_index,
173 src_table.as_v8(),
174 src_index,
175 len,
176 ),
177 #[cfg(feature = "js")]
178 BackendStore::Js(_) => crate::backend::js::entities::table::Table::copy(
179 store,
180 dst_table.as_js(),
181 dst_index,
182 src_table.as_js(),
183 src_index,
184 len,
185 ),
186 #[cfg(feature = "jsc")]
187 BackendStore::Jsc(_) => crate::backend::jsc::entities::table::Table::copy(
188 store,
189 dst_table.as_jsc(),
190 dst_index,
191 src_table.as_jsc(),
192 src_index,
193 len,
194 ),
195 }
196 }
197
198 #[inline]
199 pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, ext: VMExternTable) -> Self {
200 match &store.as_store_mut().inner.store {
201 #[cfg(feature = "sys")]
202 BackendStore::Sys(_) => Self::Sys(
203 crate::backend::sys::entities::table::Table::from_vm_extern(store, ext),
204 ),
205 #[cfg(feature = "wamr")]
206 BackendStore::Wamr(_) => {
207 Self::Wamr(crate::backend::wamr::entities::table::Table::from_vm_extern(store, ext))
208 }
209 #[cfg(feature = "wasmi")]
210 BackendStore::Wasmi(_) => Self::Wasmi(
211 crate::backend::wasmi::entities::table::Table::from_vm_extern(store, ext),
212 ),
213 #[cfg(feature = "v8")]
214 BackendStore::V8(_) => Self::V8(
215 crate::backend::v8::entities::table::Table::from_vm_extern(store, ext),
216 ),
217 #[cfg(feature = "js")]
218 BackendStore::Js(_) => Self::Js(
219 crate::backend::js::entities::table::Table::from_vm_extern(store, ext),
220 ),
221 #[cfg(feature = "jsc")]
222 BackendStore::Jsc(_) => Self::Jsc(
223 crate::backend::jsc::entities::table::Table::from_vm_extern(store, ext),
224 ),
225 }
226 }
227
228 #[inline]
230 pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
231 match_rt!(on self => s {
232 s.is_from_store(store)
233 })
234 }
235
236 #[inline]
237 pub(crate) fn to_vm_extern(&self) -> VMExtern {
238 match_rt!(on self => s {
239 s.to_vm_extern()
240 })
241 }
242}
243
244#[cfg(test)]
245mod test {
246 #[test]
248 #[cfg_attr(
249 feature = "wamr",
250 ignore = "wamr does not support direct calls to grow table"
251 )]
252 #[cfg_attr(feature = "wasmi", ignore = "wasmi does not support funcrefs")]
253 #[cfg_attr(
254 feature = "v8",
255 ignore = "growing tables in v8 is not currently supported"
256 )]
257 fn table_grow_issue_3197() {
258 use crate::{Instance, Module, Store, Table, TableType, Type, Value, imports};
259
260 const WAT: &str = r#"(module (table (import "env" "table") 100 funcref))"#;
261
262 let mut store = Store::default();
265 let module = Module::new(&store, WAT).unwrap();
266 let ty = TableType::new(Type::FuncRef, 0, None);
267 let table = Table::new(&mut store, ty, Value::FuncRef(None)).unwrap();
268 table.grow(&mut store, 100, Value::FuncRef(None)).unwrap();
269 assert_eq!(table.ty(&store).minimum, 0);
270 let imports = imports! {"env" => {"table" => table}};
271 let _instance = Instance::new(&mut store, &module, &imports).unwrap();
272 }
273}