wasm/execution/store/
instances.rs1use alloc::{collections::btree_map::BTreeMap, string::String, vec, vec::Vec};
2
3use crate::{
4 core::{
5 indices::TypeIdx,
6 reader::{
7 span::Span,
8 types::{FuncType, MemType, TableType},
9 },
10 sidetable::Sidetable,
11 },
12 linear_memory::LinearMemory,
13 value::Ref,
14 GlobalType, Limits, RefType, RuntimeError, TrapError, ValType, Value,
15};
16
17use super::{
18 addrs::{DataAddr, ElemAddr, FuncAddr, GlobalAddr, MemAddr, ModuleAddr, TableAddr},
19 ExternVal, HaltExecutionError,
20};
21
22#[derive(Debug)]
23pub enum FuncInst<T> {
25 WasmFunc(WasmFuncInst),
26 HostFunc(HostFuncInst<T>),
27}
28
29#[derive(Debug)]
30pub struct WasmFuncInst {
31 pub function_type: FuncType,
32 pub _ty: TypeIdx,
33 pub locals: Vec<ValType>,
34 pub code_expr: Span,
35 pub stp: usize,
37
38 pub module_addr: ModuleAddr,
41}
42
43#[derive(Debug)]
44pub struct HostFuncInst<T> {
45 pub function_type: FuncType,
46 pub hostcode: fn(&mut T, Vec<Value>) -> Result<Vec<Value>, HaltExecutionError>,
47}
48
49impl<T> FuncInst<T> {
50 pub fn ty(&self) -> FuncType {
51 match self {
52 FuncInst::WasmFunc(wasm_func_inst) => wasm_func_inst.function_type.clone(),
53 FuncInst::HostFunc(host_func_inst) => host_func_inst.function_type.clone(),
54 }
55 }
56}
57
58#[derive(Clone, Debug)]
59pub struct ElemInst {
61 pub _ty: RefType,
62 pub references: Vec<Ref>,
63}
64
65impl ElemInst {
66 pub fn len(&self) -> usize {
67 self.references.len()
68 }
69}
70
71#[derive(Debug)]
75pub struct TableInst {
76 pub ty: TableType,
77 pub elem: Vec<Ref>,
78}
79
80impl TableInst {
81 pub fn len(&self) -> usize {
82 self.elem.len()
83 }
84
85 pub fn grow(&mut self, n: u32, reff: Ref) -> Result<(), RuntimeError> {
87 let len = n
89 .checked_add(self.elem.len() as u32)
90 .ok_or(TrapError::TableOrElementAccessOutOfBounds)?;
91
92 if self.ty.lim.max.map(|max| len > max).unwrap_or(false) {
96 return Err(TrapError::TableOrElementAccessOutOfBounds.into());
97 }
98 let limits_prime = Limits {
99 min: len,
100 max: self.ty.lim.max,
101 };
102
103 self.elem.extend(vec![reff; n as usize]);
104
105 self.ty.lim = limits_prime;
106 Ok(())
107 }
108}
109
110pub struct MemInst {
111 pub ty: MemType,
112 pub mem: LinearMemory,
113}
114impl core::fmt::Debug for MemInst {
115 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
116 f.debug_struct("MemInst")
117 .field("ty", &self.ty)
118 .finish_non_exhaustive()
119 }
120}
121
122impl MemInst {
123 pub fn grow(&mut self, n: u32) -> Result<(), RuntimeError> {
125 let len = n + self.mem.pages() as u32;
127 if len > Limits::MAX_MEM_PAGES {
128 return Err(TrapError::MemoryOrDataAccessOutOfBounds.into());
129 }
130
131 if self.ty.limits.max.map(|max| len > max).unwrap_or(false) {
135 return Err(TrapError::MemoryOrDataAccessOutOfBounds.into());
136 }
137 let limits_prime = Limits {
138 min: len,
139 max: self.ty.limits.max,
140 };
141
142 self.mem.grow(n.try_into().unwrap());
143
144 self.ty.limits = limits_prime;
145 Ok(())
146 }
147
148 pub fn size(&self) -> usize {
150 self.mem.len() / (crate::Limits::MEM_PAGE_SIZE as usize)
151 }
152}
153
154#[derive(Debug)]
160pub struct GlobalInst {
161 pub ty: GlobalType,
162 pub value: Value,
164}
165
166pub struct DataInst {
167 pub data: Vec<u8>,
168}
169
170impl core::fmt::Debug for DataInst {
171 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
172 f.debug_struct("DataInst").finish_non_exhaustive()
173 }
174}
175
176#[derive(Debug)]
178pub struct ModuleInst<'b> {
179 pub types: Vec<FuncType>,
180 pub func_addrs: Vec<FuncAddr>,
181 pub table_addrs: Vec<TableAddr>,
182 pub mem_addrs: Vec<MemAddr>,
183 pub global_addrs: Vec<GlobalAddr>,
184 pub elem_addrs: Vec<ElemAddr>,
185 pub data_addrs: Vec<DataAddr>,
186 pub exports: BTreeMap<String, ExternVal>,
191
192 pub wasm_bytecode: &'b [u8],
194
195 pub sidetable: Sidetable,
197}