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    #[inline(always)]
19    fn instruction_hook(&mut self, _bytecode: &[u8], _pc: usize) {}
20
21    /// Amount of fuel to be deducted when a single byte `instr` is hit. The cost corresponding to `UNREACHABLE` and
22    /// `END` instructions and other bytes that do not correspond to any Wasm instruction are ignored.
23    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
24    // yields constants.
25    #[inline(always)]
26    fn get_flat_cost(_instr: u8) -> u64 {
27        1
28    }
29
30    /// Amount of fuel to be deducted when a multi-byte instruction that starts with the byte 0xFC is hit. This method
31    /// should return the cost of an instruction obtained by prepending 0xFC to of an unsigned 32-bit LEB
32    /// representation of `instr`. Multi-byte sequences obtained this way that do not correspond to any Wasm instruction
33    /// are ignored.
34    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
35    // yields constants.
36    #[inline(always)]
37    fn get_fc_extension_flat_cost(_instr: u32) -> u64 {
38        1
39    }
40
41    /// Amount of fuel to be deducted when a multi-byte instruction that starts with the byte 0xFD is hit. This method
42    /// should return the cost of an instruction obtained by prepending 0xFD to of an unsigned 32-bit LEB
43    /// representation of `instr`. Multi-byte sequences obtained this way that do not correspond to any Wasm instruction
44    /// are ignored.
45    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
46    // yields constants.
47    #[inline(always)]
48    fn get_fd_extension_flat_cost(_instr: u32) -> u64 {
49        1
50    }
51
52    /// Amount of fuel to be deducted per element of a single byte instruction `instr` that executes in asymptotically
53    /// linear time with respect to one of the values it pops from the stack.
54    ///
55    /// In Wasm 2.0 specification, this applies to the following instructions:
56    /// - `MEMORY.GROW` of type `[n: i32] -> [i32]`
57    ///
58    /// The cost of the instruction is calculated as `cost := get_flat_cost(instr) + n*get_cost_per_element(instr)`.
59    /// where `n` is the stack value marked in the instruction type signature above. Other instructions and bytes that
60    /// do not correspond to any instruction are ignored.
61    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
62    // yields constants.
63    #[inline(always)]
64    fn get_cost_per_element(_instr: u8) -> u64 {
65        0
66    }
67
68    /// Amount of fuel to be deducted per element of a  multi-byte instruction that starts with the byte 0xFC,
69    /// which executes in asymptotically linear time with respect to one of the values it pops from the stack. This
70    /// method should return the cost of an instruction obtained by prepending 0xFD to of an unsigned 32-bit LEB
71    /// representation of `instr`. Multi-byte sequences obtained this way that do not correspond to any Wasm instruction
72    /// are ignored.
73    ///
74    /// In Wasm 2.0 specification, this applies to the following instructions:
75    /// - `MEMORY.INIT x`  of type `[d:i32 s: i32 n: i32] -> []`
76    /// - `MEMORY.FILL`    of type `[d: i32 val: i32 n: i32] -> []`
77    /// - `MEMORY.COPY`    of type `[d: i32 s: i32 n: i32] -> []`
78    /// - `TABLE.GROW x`   of type `[val: ref n: i32] -> [i32]`
79    /// - `TABLE.INIT x y` of type `[d: i32 s: i32 n: i32] -> []`
80    /// - `TABLE.FILL x`   of type `[i: i32 val: ref n: i32] -> []`
81    /// - `TABLE.COPY x y` of type `[d: i32 s: i32 n: i32] -> []`
82    ///
83    /// The cost of the instruction is calculated as `cost := get_flat_cost(instr) + n*get_cost_per_element(instr)`.
84    /// where `n` is the stack value marked in the instruction type signature above. Other instructions and multi-byte
85    /// sequences that do not correspond to any instruction are ignored.
86    // It must always be checked that the calls to this method fold into a constant if it is just a match statement that
87    // yields constants.
88    #[inline(always)]
89    fn get_fc_extension_cost_per_element(_instr: u32) -> u64 {
90        0
91    }
92}
93
94/// Default implementation of the interpreter configuration, with all hooks empty
95impl Config for () {}