wasm/execution/
resumable.rs

1//! TODO
2
3use core::num::NonZeroU64;
4
5use alloc::vec::Vec;
6
7use crate::{addrs::FuncAddr, value_stack::Stack, Hostcode, Value};
8
9/// A [`WasmResumable`] is an object used to resume execution of Wasm code.
10///
11/// # Safety
12///
13/// TODO:
14///
15/// - stack must be initialized with correct parameters to function
16///   referenced by function address
17/// - program counter must be valid for the bytecode of function referenced by the function address
18/// - stp must point to the correct sidetable entry for the function referenced by function address
19#[derive(Debug)]
20pub struct WasmResumable {
21    pub(crate) stack: Stack,
22    pub(crate) pc: usize,
23    pub(crate) stp: usize,
24    pub(crate) current_func_addr: FuncAddr,
25    pub(crate) maybe_fuel: Option<u64>,
26}
27
28impl WasmResumable {
29    pub fn fuel(&self) -> Option<u64> {
30        self.maybe_fuel
31    }
32
33    pub fn fuel_mut(&mut self) -> &mut Option<u64> {
34        &mut self.maybe_fuel
35    }
36}
37
38/// A [`HostCall`] object contains information required for executing a specific
39/// host function.
40#[derive(Clone, Debug)]
41pub struct HostCall {
42    /// Must contain the correct parameter types for the host function with host
43    /// code `hostcode`.
44    pub params: Vec<Value>,
45    pub hostcode: Hostcode,
46}
47
48/// A [`HostResumable`] is used to resume execution after executing its
49/// [`HostCall`].
50///
51/// When a host function is called, a [`HostResumable`] and [`HostCall`] are
52/// returned. After the [`HostCall`] was used to execute the host function, the
53/// [`HostResumable`] is used together with the return values of the host call
54/// to resume execution.
55#[derive(Debug)]
56pub struct HostResumable {
57    pub(crate) host_func_addr: FuncAddr,
58    pub(crate) inner_resumable: Option<WasmResumable>,
59    /// Hack: This is `Some` only if `inner_resumable` is `None`. In that case
60    /// it is used to store the maybe_fuel, so it can be returned in
61    /// [`RunState::Finished`] later.
62    pub(crate) maybe_fuel: Option<Option<u64>>,
63}
64
65#[derive(Debug)]
66pub enum Resumable {
67    Wasm(WasmResumable),
68    Host {
69        host_call: HostCall,
70        host_resumable: HostResumable,
71    },
72}
73
74impl Resumable {
75    /// Tries to convert this [`Resumable`] into a [`WasmResumable`]
76    pub fn as_wasm(self) -> Option<WasmResumable> {
77        match self {
78            Self::Wasm(wasm_resumable) => Some(wasm_resumable),
79            Self::Host { .. } => None,
80        }
81    }
82
83    /// Tries to convert this [`Resumable`] into a [`HostCall`] and
84    /// [`HostResumable`]
85    pub fn as_host(self) -> Option<(HostCall, HostResumable)> {
86        match self {
87            Self::Wasm(_) => None,
88            Self::Host {
89                host_call,
90                host_resumable,
91            } => Some((host_call, host_resumable)),
92        }
93    }
94}
95
96/// Represents the state of a possibly interrupted resumable.
97pub enum RunState {
98    /// represents a resumable that has executed completely with return values `values` and possibly remaining fuel
99    /// `maybe_remaining_fuel` (has `Some(remaining_fuel)` for fuel-metered operations and `None` otherwise)
100    Finished {
101        values: Vec<Value>,
102        maybe_remaining_fuel: Option<u64>,
103    },
104    /// represents a resumable that has ran out of fuel during execution, missing at least `required_fuel` units of fuel
105    /// to continue further execution (this is None if unknown).
106    Resumable {
107        resumable: WasmResumable,
108        required_fuel: Option<NonZeroU64>,
109    },
110    /// A host function was called by Wasm code. Use the [`HostCall`] to execute
111    /// the host function and resume execution using the [`HostResumable`] and
112    /// the return values produced by execution.
113    HostCalled {
114        host_call: HostCall,
115        resumable: HostResumable,
116    },
117}