1use crate::{
2 host::Externals,
3 isa,
4 module::ModuleInstance,
5 runner::{check_function_args, Interpreter, InterpreterState, StackRecycler},
6 RuntimeValue,
7 Signature,
8 Trap,
9 ValueType,
10};
11use alloc::{
12 borrow::Cow,
13 rc::{Rc, Weak},
14 vec::Vec,
15};
16use casper_wasm::elements::Local;
17use core::fmt;
18
19#[derive(Clone, Debug)]
25pub struct FuncRef(Rc<FuncInstance>);
26
27impl ::core::ops::Deref for FuncRef {
28 type Target = FuncInstance;
29 fn deref(&self) -> &FuncInstance {
30 &self.0
31 }
32}
33
34pub struct FuncInstance(FuncInstanceInternal);
49
50#[derive(Clone)]
51pub(crate) enum FuncInstanceInternal {
52 Internal {
53 signature: Rc<Signature>,
54 module: Weak<ModuleInstance>,
55 body: Rc<FuncBody>,
56 },
57 Host {
58 signature: Signature,
59 host_func_index: usize,
60 },
61}
62
63impl fmt::Debug for FuncInstance {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 match self.as_internal() {
66 FuncInstanceInternal::Internal { ref signature, .. } => {
67 write!(f, "Internal {{ signature={:?} }}", signature,)
70 }
71 FuncInstanceInternal::Host { ref signature, .. } => {
72 write!(f, "Host {{ signature={:?} }}", signature)
73 }
74 }
75 }
76}
77
78impl FuncInstance {
79 pub fn alloc_host(signature: Signature, host_func_index: usize) -> FuncRef {
88 let func = FuncInstanceInternal::Host {
89 signature,
90 host_func_index,
91 };
92 FuncRef(Rc::new(FuncInstance(func)))
93 }
94
95 pub fn signature(&self) -> &Signature {
101 match *self.as_internal() {
102 FuncInstanceInternal::Internal { ref signature, .. } => signature,
103 FuncInstanceInternal::Host { ref signature, .. } => signature,
104 }
105 }
106
107 pub(crate) fn as_internal(&self) -> &FuncInstanceInternal {
108 &self.0
109 }
110
111 pub(crate) fn alloc_internal(
112 module: Weak<ModuleInstance>,
113 signature: Rc<Signature>,
114 body: FuncBody,
115 ) -> FuncRef {
116 let func = FuncInstanceInternal::Internal {
117 signature,
118 module,
119 body: Rc::new(body),
120 };
121 FuncRef(Rc::new(FuncInstance(func)))
122 }
123
124 pub(crate) fn body(&self) -> Option<Rc<FuncBody>> {
125 match *self.as_internal() {
126 FuncInstanceInternal::Internal { ref body, .. } => Some(Rc::clone(body)),
127 FuncInstanceInternal::Host { .. } => None,
128 }
129 }
130
131 pub fn invoke<E: Externals>(
141 func: &FuncRef,
142 args: &[RuntimeValue],
143 externals: &mut E,
144 ) -> Result<Option<RuntimeValue>, Trap> {
145 check_function_args(func.signature(), args)?;
146 match *func.as_internal() {
147 FuncInstanceInternal::Internal { .. } => {
148 let mut interpreter = Interpreter::new(func, args, None)?;
149 interpreter.start_execution(externals)
150 }
151 FuncInstanceInternal::Host {
152 ref host_func_index,
153 ..
154 } => externals.invoke_index(*host_func_index, args.into()),
155 }
156 }
157
158 pub fn invoke_with_stack<E: Externals>(
166 func: &FuncRef,
167 args: &[RuntimeValue],
168 externals: &mut E,
169 stack_recycler: &mut StackRecycler,
170 ) -> Result<Option<RuntimeValue>, Trap> {
171 check_function_args(func.signature(), args)?;
172 match *func.as_internal() {
173 FuncInstanceInternal::Internal { .. } => {
174 let mut interpreter = Interpreter::new(func, args, Some(stack_recycler))?;
175 let return_value = interpreter.start_execution(externals);
176 stack_recycler.recycle(interpreter);
177 return_value
178 }
179 FuncInstanceInternal::Host {
180 ref host_func_index,
181 ..
182 } => externals.invoke_index(*host_func_index, args.into()),
183 }
184 }
185
186 pub fn invoke_resumable<'args>(
201 func: &FuncRef,
202 args: impl Into<Cow<'args, [RuntimeValue]>>,
203 ) -> Result<FuncInvocation<'args>, Trap> {
204 let args = args.into();
205 check_function_args(func.signature(), &args)?;
206 match *func.as_internal() {
207 FuncInstanceInternal::Internal { .. } => {
208 let interpreter = Interpreter::new(func, &args, None)?;
209 Ok(FuncInvocation {
210 kind: FuncInvocationKind::Internal(interpreter),
211 })
212 }
213 FuncInstanceInternal::Host {
214 ref host_func_index,
215 ..
216 } => Ok(FuncInvocation {
217 kind: FuncInvocationKind::Host {
218 args,
219 host_func_index: *host_func_index,
220 finished: false,
221 },
222 }),
223 }
224 }
225}
226
227#[derive(Debug)]
229pub enum ResumableError {
230 Trap(Trap),
232 NotResumable,
243 AlreadyStarted,
249}
250
251impl From<Trap> for ResumableError {
252 fn from(trap: Trap) -> Self {
253 ResumableError::Trap(trap)
254 }
255}
256
257pub struct FuncInvocation<'args> {
259 kind: FuncInvocationKind<'args>,
260}
261
262enum FuncInvocationKind<'args> {
263 Internal(Interpreter),
264 Host {
265 args: Cow<'args, [RuntimeValue]>,
266 host_func_index: usize,
267 finished: bool,
268 },
269}
270
271impl FuncInvocation<'_> {
272 pub fn is_resumable(&self) -> bool {
274 match &self.kind {
275 FuncInvocationKind::Internal(ref interpreter) => interpreter.state().is_resumable(),
276 FuncInvocationKind::Host { .. } => false,
277 }
278 }
279
280 pub fn resumable_value_type(&self) -> Option<ValueType> {
282 match &self.kind {
283 FuncInvocationKind::Internal(ref interpreter) => match interpreter.state() {
284 InterpreterState::Resumable(ref value_type) => *value_type,
285 _ => None,
286 },
287 FuncInvocationKind::Host { .. } => None,
288 }
289 }
290
291 pub fn start_execution<'externals, E: Externals + 'externals>(
293 &mut self,
294 externals: &'externals mut E,
295 ) -> Result<Option<RuntimeValue>, ResumableError> {
296 match self.kind {
297 FuncInvocationKind::Internal(ref mut interpreter) => {
298 if interpreter.state() != &InterpreterState::Initialized {
299 return Err(ResumableError::AlreadyStarted);
300 }
301 Ok(interpreter.start_execution(externals)?)
302 }
303 FuncInvocationKind::Host {
304 ref args,
305 ref mut finished,
306 ref host_func_index,
307 } => {
308 if *finished {
309 return Err(ResumableError::AlreadyStarted);
310 }
311 *finished = true;
312 Ok(externals.invoke_index(*host_func_index, args.as_ref().into())?)
313 }
314 }
315 }
316
317 pub fn resume_execution<'externals, E: Externals + 'externals>(
326 &mut self,
327 return_val: Option<RuntimeValue>,
328 externals: &'externals mut E,
329 ) -> Result<Option<RuntimeValue>, ResumableError> {
330 use crate::TrapCode;
331
332 if return_val.map(|v| v.value_type()) != self.resumable_value_type() {
333 return Err(ResumableError::Trap(Trap::from(
334 TrapCode::UnexpectedSignature,
335 )));
336 }
337
338 match &mut self.kind {
339 FuncInvocationKind::Internal(interpreter) => {
340 if interpreter.state().is_resumable() {
341 Ok(interpreter.resume_execution(return_val, externals)?)
342 } else {
343 Err(ResumableError::AlreadyStarted)
344 }
345 }
346 FuncInvocationKind::Host { .. } => Err(ResumableError::NotResumable),
347 }
348 }
349}
350
351#[derive(Clone, Debug)]
352pub struct FuncBody {
353 pub locals: Vec<Local>,
354 pub code: isa::Instructions,
355}