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 () {}