Skip to main content

wasmi/engine/executor/instrs/
utils.rs

1use super::Executor;
2use crate::{
3    ir::{index::Memory, Offset64Hi, Slot},
4    store::StoreInner,
5};
6
7#[cfg(doc)]
8use crate::ir::Op;
9
10macro_rules! impl_unary_executors {
11    ( $( (Op::$var_name:ident, $fn_name:ident, $op:expr) ),* $(,)? ) => {
12        $(
13            #[doc = concat!("Executes an [`Op::", stringify!($var_name), "`].")]
14            pub fn $fn_name(&mut self, result: Slot, input: Slot) {
15                self.execute_unary(result, input, $op)
16            }
17        )*
18    };
19}
20
21macro_rules! impl_binary_executors {
22    ( $( (Op::$var_name:ident, $fn_name:ident, $op:expr) ),* $(,)? ) => {
23        $(
24            #[doc = concat!("Executes an [`Op::", stringify!($var_name), "`].")]
25            pub fn $fn_name(&mut self, result: Slot, lhs: Slot, rhs: Slot) {
26                self.execute_binary(result, lhs, rhs, $op)
27            }
28        )*
29    };
30}
31
32impl Executor<'_> {
33    /// Returns the register `value` and `offset` parameters for a `load` [`Op`].
34    pub fn fetch_value_and_offset_hi(&self) -> (Slot, Offset64Hi) {
35        // Safety: Wasmi translation guarantees that `Op::SlotAndImm32` exists.
36        unsafe { self.fetch_reg_and_offset_hi() }
37    }
38
39    /// Fetches the bytes of the default memory at index 0.
40    pub fn fetch_default_memory_bytes(&self) -> &[u8] {
41        // Safety: the `self.cache.memory` pointer is always synchronized
42        //         conservatively whenever it could have been invalidated.
43        unsafe { self.cache.memory.data() }
44    }
45
46    /// Fetches the bytes of the given `memory`.
47    pub fn fetch_memory_bytes<'exec, 'store, 'bytes>(
48        &'exec self,
49        memory: Memory,
50        store: &'store StoreInner,
51    ) -> &'bytes [u8]
52    where
53        'exec: 'bytes,
54        'store: 'bytes,
55    {
56        match memory.is_default() {
57            true => self.fetch_default_memory_bytes(),
58            false => self.fetch_non_default_memory_bytes(memory, store),
59        }
60    }
61
62    /// Fetches the bytes of the given non-default `memory`.
63    #[cold]
64    pub fn fetch_non_default_memory_bytes<'exec, 'store, 'bytes>(
65        &'exec self,
66        memory: Memory,
67        store: &'store StoreInner,
68    ) -> &'bytes [u8]
69    where
70        'exec: 'bytes,
71        'store: 'bytes,
72    {
73        let memory = self.get_memory(memory);
74        store.resolve_memory(&memory).data()
75    }
76
77    /// Fetches the bytes of the default memory at index 0.
78    #[inline]
79    pub fn fetch_default_memory_bytes_mut(&mut self) -> &mut [u8] {
80        // Safety: the `self.cache.memory` pointer is always synchronized
81        //         conservatively whenever it could have been invalidated.
82        unsafe { self.cache.memory.data_mut() }
83    }
84
85    /// Fetches the bytes of the given `memory`.
86    #[inline]
87    pub fn fetch_memory_bytes_mut<'exec, 'store, 'bytes>(
88        &'exec mut self,
89        memory: Memory,
90        store: &'store mut StoreInner,
91    ) -> &'bytes mut [u8]
92    where
93        'exec: 'bytes,
94        'store: 'bytes,
95    {
96        match memory.is_default() {
97            true => self.fetch_default_memory_bytes_mut(),
98            false => self.fetch_non_default_memory_bytes_mut(memory, store),
99        }
100    }
101
102    /// Fetches the bytes of the given non-default `memory`.
103    #[cold]
104    #[inline]
105    pub fn fetch_non_default_memory_bytes_mut<'exec, 'store, 'bytes>(
106        &'exec mut self,
107        memory: Memory,
108        store: &'store mut StoreInner,
109    ) -> &'bytes mut [u8]
110    where
111        'exec: 'bytes,
112        'store: 'bytes,
113    {
114        let memory = self.get_memory(memory);
115        store.resolve_memory_mut(&memory).data_mut()
116    }
117}