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 = "v8")]
43 BackendStore::V8(_) => Ok(Self::V8(crate::backend::v8::entities::table::Table::new(
44 store, ty, init,
45 )?)),
46 #[cfg(feature = "js")]
47 BackendStore::Js(_) => Ok(Self::Js(crate::backend::js::entities::table::Table::new(
48 store, ty, init,
49 )?)),
50 }
51 }
52
53 #[inline]
55 pub fn ty(&self, store: &impl AsStoreRef) -> TableType {
56 match_rt!(on self => s {
57 s.ty(store)
58 })
59 }
60
61 #[inline]
63 pub fn get(&self, store: &mut impl AsStoreMut, index: u32) -> Option<Value> {
64 match_rt!(on self => s {
65 s.get(store, index)
66 })
67 }
68
69 #[inline]
71 pub fn set(
72 &self,
73 store: &mut impl AsStoreMut,
74 index: u32,
75 val: Value,
76 ) -> Result<(), RuntimeError> {
77 match_rt!(on self => s {
78 s.set(store, index, val)
79 })
80 }
81
82 #[inline]
84 pub fn size(&self, store: &impl AsStoreRef) -> u32 {
85 match_rt!(on self => s {
86 s.size(store)
87 })
88 }
89
90 #[inline]
100 pub fn grow(
101 &self,
102 store: &mut impl AsStoreMut,
103 delta: u32,
104 init: Value,
105 ) -> Result<u32, RuntimeError> {
106 match_rt!(on self => s {
107 s.grow(store, delta, init)
108 })
109 }
110
111 #[inline]
119 pub fn copy(
120 store: &mut impl AsStoreMut,
121 dst_table: &Self,
122 dst_index: u32,
123 src_table: &Self,
124 src_index: u32,
125 len: u32,
126 ) -> Result<(), RuntimeError> {
127 match &store.as_store_mut().inner.store {
128 #[cfg(feature = "sys")]
129 BackendStore::Sys(_) => crate::backend::sys::entities::table::Table::copy(
130 store,
131 dst_table.as_sys(),
132 dst_index,
133 src_table.as_sys(),
134 src_index,
135 len,
136 ),
137
138 #[cfg(feature = "v8")]
139 BackendStore::V8(_) => crate::backend::v8::entities::table::Table::copy(
140 store,
141 dst_table.as_v8(),
142 dst_index,
143 src_table.as_v8(),
144 src_index,
145 len,
146 ),
147 #[cfg(feature = "js")]
148 BackendStore::Js(_) => crate::backend::js::entities::table::Table::copy(
149 store,
150 dst_table.as_js(),
151 dst_index,
152 src_table.as_js(),
153 src_index,
154 len,
155 ),
156 }
157 }
158
159 #[inline]
160 pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, ext: VMExternTable) -> Self {
161 match &store.as_store_mut().inner.store {
162 #[cfg(feature = "sys")]
163 BackendStore::Sys(_) => Self::Sys(
164 crate::backend::sys::entities::table::Table::from_vm_extern(store, ext),
165 ),
166 #[cfg(feature = "v8")]
167 BackendStore::V8(_) => Self::V8(
168 crate::backend::v8::entities::table::Table::from_vm_extern(store, ext),
169 ),
170 #[cfg(feature = "js")]
171 BackendStore::Js(_) => Self::Js(
172 crate::backend::js::entities::table::Table::from_vm_extern(store, ext),
173 ),
174 }
175 }
176
177 #[inline]
179 pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
180 match_rt!(on self => s {
181 s.is_from_store(store)
182 })
183 }
184
185 #[inline]
186 pub(crate) fn to_vm_extern(&self) -> VMExtern {
187 match_rt!(on self => s {
188 s.to_vm_extern()
189 })
190 }
191}
192
193#[cfg(test)]
194mod test {
195 #[test]
197 #[cfg_attr(
198 feature = "v8",
199 ignore = "growing tables in v8 is not currently supported"
200 )]
201 fn table_grow_issue_3197() {
202 use crate::{Instance, Module, Store, Table, TableType, Type, Value, imports};
203
204 const WAT: &str = r#"(module (table (import "env" "table") 100 funcref))"#;
205
206 let mut store = Store::default();
209 let module = Module::new(&store, WAT).unwrap();
210 let ty = TableType::new(Type::FuncRef, 0, None);
211 let table = Table::new(&mut store, ty, Value::FuncRef(None)).unwrap();
212 table.grow(&mut store, 100, Value::FuncRef(None)).unwrap();
213 assert_eq!(table.ty(&store).minimum, 0);
214 let imports = imports! {"env" => {"table" => table}};
215 let _instance = Instance::new(&mut store, &module, &imports).unwrap();
216 }
217}