wasm/execution/
config.rs

1/// Trait that allows user specified configuration for various items during interpretation. Additionally, the types
2/// implementing this trait can act as custom user data within an interpreter instance, passed along to each method of
3/// this trait and host functions whenever they are invoked.
4///
5/// The default implementation of all trait methods have the least overhead, i. e. most can be optimized out fully.
6// It must always be checked that there is no additional performance penalty for the default config!
7pub trait Config {
8    /// Maximum number of values in the value stack
9    const MAX_VALUE_STACK_SIZE: usize = 0xf0000; // 64 Kibi-Values
10
11    /// Maximum number of cascading function invocations
12    const MAX_CALL_STACK_SIZE: usize = 0x1000; // 4 Kibi-Functions
13
14    /// A hook which is called before every wasm instruction
15    ///
16    /// This allows the most intricate insight into the interpreters behavior, at the cost of a
17    /// hefty performance penalty
18    #[allow(unused_variables)]
19    #[inline(always)]
20    fn instruction_hook(&mut self, bytecode: &[u8], pc: usize) {}
21
22    /// Amount of fuel to be deducted when a single byte `instr` is hit. The cost corresponding to `UNREACHABLE` and
23    /// `END` instructions and other bytes that do not correspond to any Wasm instruction are ignored.
24    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
25    // yields constants.
26    #[inline(always)]
27    fn get_flat_cost(_instr: u8) -> u32 {
28        1
29    }
30
31    /// Amount of fuel to be deducted when a multi-byte instruction that starts with the byte 0xFC is hit. This method
32    /// should return the cost of an instruction obtained by prepending 0xFC to of an unsigned 32-bit LEB
33    /// representation of `instr`. Multi-byte sequences obtained this way that do not correspond to any Wasm instruction
34    /// are ignored.
35    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
36    // yields constants.
37    #[inline(always)]
38    fn get_fc_extension_flat_cost(_instr: u32) -> u32 {
39        1
40    }
41
42    /// Amount of fuel to be deducted when a multi-byte instruction that starts with the byte 0xFD is hit. This method
43    /// should return the cost of an instruction obtained by prepending 0xFD to of an unsigned 32-bit LEB
44    /// representation of `instr`. Multi-byte sequences obtained this way that do not correspond to any Wasm instruction
45    /// are ignored.
46    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
47    // yields constants.
48    #[inline(always)]
49    fn get_fd_extension_flat_cost(_instr: u32) -> u32 {
50        1
51    }
52
53    /// Amount of fuel to be deducted per element of a single byte instruction `instr` that executes in asymptotically
54    /// linear time with respect to one of the values it pops from the stack.
55    ///
56    /// In Wasm 2.0 specification, this applies to the following instructions:
57    /// - `MEMORY.GROW` of type `[n: i32] -> [i32]`
58    ///
59    /// The cost of the instruction is calculated as `cost := get_flat_cost(instr) + n*get_cost_per_element(instr)`.
60    /// where `n` is the stack value marked in the instruction type signature above. Other instructions and bytes that
61    /// do not correspond to any instruction are ignored.
62    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
63    // yields constants.
64    #[inline(always)]
65    fn get_cost_per_element(_instr: u8) -> u32 {
66        0
67    }
68
69    /// Amount of fuel to be deducted per element of a  multi-byte instruction that starts with the byte 0xFC,
70    /// which executes in asymptotically linear time with respect to one of the values it pops from the stack. This
71    /// method should return the cost of an instruction obtained by prepending 0xFD to of an unsigned 32-bit LEB
72    /// representation of `instr`. Multi-byte sequences obtained this way that do not correspond to any Wasm instruction
73    /// are ignored.
74    ///
75    /// In Wasm 2.0 specification, this applies to the following instructions:
76    /// - `MEMORY.INIT x`  of type `[d:i32 s: i32 n: i32] -> []`
77    /// - `MEMORY.FILL`    of type `[d: i32 val: i32 n: i32] -> []`
78    /// - `MEMORY.COPY`    of type `[d: i32 s: i32 n: i32] -> []`
79    /// - `TABLE.GROW x`   of type `[val: ref n: i32] -> [i32]`
80    /// - `TABLE.INIT x y` of type `[d: i32 s: i32 n: i32] -> []`
81    /// - `TABLE.FILL x`   of type `[i: i32 val: ref n: i32] -> []`
82    /// - `TABLE.COPY x y` of type `[d: i32 s: i32 n: i32] -> []`
83    ///
84    /// The cost of the instruction is calculated as `cost := get_flat_cost(instr) + n*get_cost_per_element(instr)`.
85    /// where `n` is the stack value marked in the instruction type signature above. Other instructions and multi-byte
86    /// sequences that do not correspond to any instruction are ignored.
87    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
88    // yields constants.
89    #[inline(always)]
90    fn get_fc_extension_cost_per_element(_instr: u32) -> u32 {
91        0
92    }
93}
94
95/// Default implementation of the interpreter configuration, with all hooks empty
96impl Config for () {}