1#[allow(unused_imports)]
2use alloc::prelude::v1::*;
3use alloc::rc::{Rc, Weak};
4use core::fmt;
5use host::Externals;
6use isa;
7use module::ModuleInstance;
8use xwasm::elements::Local;
9use runner::{check_function_args, Interpreter, InterpreterState};
10use types::ValueType;
11use value::RuntimeValue;
12use {Signature, Trap};
13
14#[derive(Clone, Debug)]
20pub struct FuncRef(Rc<FuncInstance>);
21
22impl ::core::ops::Deref for FuncRef {
23 type Target = FuncInstance;
24 fn deref(&self) -> &FuncInstance {
25 &self.0
26 }
27}
28
29pub struct FuncInstance(FuncInstanceInternal);
44
45#[derive(Clone)]
46pub(crate) enum FuncInstanceInternal {
47 Internal {
48 signature: Rc<Signature>,
49 module: Weak<ModuleInstance>,
50 body: Rc<FuncBody>,
51 },
52 Host {
53 signature: Signature,
54 host_func_index: usize,
55 },
56}
57
58impl fmt::Debug for FuncInstance {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 match self.as_internal() {
61 &FuncInstanceInternal::Internal { ref signature, .. } => {
62 write!(f, "Internal {{ signature={:?} }}", signature,)
65 }
66 &FuncInstanceInternal::Host { ref signature, .. } => {
67 write!(f, "Host {{ signature={:?} }}", signature)
68 }
69 }
70 }
71}
72
73impl FuncInstance {
74 pub fn alloc_host(signature: Signature, host_func_index: usize) -> FuncRef {
83 let func = FuncInstanceInternal::Host {
84 signature,
85 host_func_index,
86 };
87 FuncRef(Rc::new(FuncInstance(func)))
88 }
89
90 pub fn signature(&self) -> &Signature {
96 match *self.as_internal() {
97 FuncInstanceInternal::Internal { ref signature, .. } => signature,
98 FuncInstanceInternal::Host { ref signature, .. } => signature,
99 }
100 }
101
102 pub(crate) fn as_internal(&self) -> &FuncInstanceInternal {
103 &self.0
104 }
105
106 pub(crate) fn alloc_internal(
107 module: Weak<ModuleInstance>,
108 signature: Rc<Signature>,
109 body: FuncBody,
110 ) -> FuncRef {
111 let func = FuncInstanceInternal::Internal {
112 signature,
113 module: module,
114 body: Rc::new(body),
115 };
116 FuncRef(Rc::new(FuncInstance(func)))
117 }
118
119 pub(crate) fn body(&self) -> Option<Rc<FuncBody>> {
120 match *self.as_internal() {
121 FuncInstanceInternal::Internal { ref body, .. } => Some(Rc::clone(body)),
122 FuncInstanceInternal::Host { .. } => None,
123 }
124 }
125
126 pub fn invoke<E: Externals>(
136 func: &FuncRef,
137 args: &[RuntimeValue],
138 externals: &mut E,
139 ) -> Result<Option<RuntimeValue>, Trap> {
140 check_function_args(func.signature(), &args)?;
141 match *func.as_internal() {
142 FuncInstanceInternal::Internal { .. } => {
143 let mut interpreter = Interpreter::new(func, args)?;
144 interpreter.start_execution(externals)
145 }
146 FuncInstanceInternal::Host {
147 ref host_func_index,
148 ..
149 } => externals.invoke_index(*host_func_index, args.into()),
150 }
151 }
152
153 pub fn invoke_resumable<'args>(
168 func: &FuncRef,
169 args: &'args [RuntimeValue],
170 ) -> Result<FuncInvocation<'args>, Trap> {
171 check_function_args(func.signature(), &args)?;
172 match *func.as_internal() {
173 FuncInstanceInternal::Internal { .. } => {
174 let interpreter = Interpreter::new(func, args)?;
175 Ok(FuncInvocation {
176 kind: FuncInvocationKind::Internal(interpreter),
177 })
178 }
179 FuncInstanceInternal::Host {
180 ref host_func_index,
181 ..
182 } => Ok(FuncInvocation {
183 kind: FuncInvocationKind::Host {
184 args,
185 host_func_index: *host_func_index,
186 finished: false,
187 },
188 }),
189 }
190 }
191}
192
193#[derive(Debug)]
195pub enum ResumableError {
196 Trap(Trap),
198 NotResumable,
209 AlreadyStarted,
215}
216
217impl From<Trap> for ResumableError {
218 fn from(trap: Trap) -> Self {
219 ResumableError::Trap(trap)
220 }
221}
222
223pub struct FuncInvocation<'args> {
225 kind: FuncInvocationKind<'args>,
226}
227
228enum FuncInvocationKind<'args> {
229 Internal(Interpreter),
230 Host {
231 args: &'args [RuntimeValue],
232 host_func_index: usize,
233 finished: bool,
234 },
235}
236
237impl<'args> FuncInvocation<'args> {
238 pub fn is_resumable(&self) -> bool {
240 match &self.kind {
241 &FuncInvocationKind::Internal(ref interpreter) => interpreter.state().is_resumable(),
242 &FuncInvocationKind::Host { .. } => false,
243 }
244 }
245
246 pub fn resumable_value_type(&self) -> Option<ValueType> {
248 match &self.kind {
249 &FuncInvocationKind::Internal(ref interpreter) => match interpreter.state() {
250 &InterpreterState::Resumable(ref value_type) => value_type.clone(),
251 _ => None,
252 },
253 &FuncInvocationKind::Host { .. } => None,
254 }
255 }
256
257 pub fn start_execution<'externals, E: Externals + 'externals>(
259 &mut self,
260 externals: &'externals mut E,
261 ) -> Result<Option<RuntimeValue>, ResumableError> {
262 match self.kind {
263 FuncInvocationKind::Internal(ref mut interpreter) => {
264 if interpreter.state() != &InterpreterState::Initialized {
265 return Err(ResumableError::AlreadyStarted);
266 }
267 Ok(interpreter.start_execution(externals)?)
268 }
269 FuncInvocationKind::Host {
270 ref args,
271 ref mut finished,
272 ref host_func_index,
273 } => {
274 if *finished {
275 return Err(ResumableError::AlreadyStarted);
276 }
277 *finished = true;
278 Ok(externals.invoke_index(*host_func_index, args.clone().into())?)
279 }
280 }
281 }
282
283 pub fn resume_execution<'externals, E: Externals + 'externals>(
292 &mut self,
293 return_val: Option<RuntimeValue>,
294 externals: &'externals mut E,
295 ) -> Result<Option<RuntimeValue>, ResumableError> {
296 use crate::TrapKind;
297
298 if return_val.map(|v| v.value_type()) != self.resumable_value_type() {
299 return Err(ResumableError::Trap(Trap::new(
300 TrapKind::UnexpectedSignature,
301 )));
302 }
303
304 match &mut self.kind {
305 FuncInvocationKind::Internal(interpreter) => {
306 if interpreter.state().is_resumable() {
307 Ok(interpreter.resume_execution(return_val, externals)?)
308 } else {
309 Err(ResumableError::AlreadyStarted)
310 }
311 }
312 FuncInvocationKind::Host { .. } => Err(ResumableError::NotResumable),
313 }
314 }
315}
316
317#[derive(Clone, Debug)]
318pub struct FuncBody {
319 pub locals: Vec<Local>,
320 pub code: isa::Instructions,
321}