@@ -17,6 +17,7 @@ use crate::{
17
17
engine:: bytecode:: Instruction ,
18
18
module:: { FuncIdx , ModuleHeader } ,
19
19
store:: { Fuel , FuelError } ,
20
+ Config ,
20
21
Error ,
21
22
} ;
22
23
use core:: {
@@ -31,7 +32,7 @@ use core::{
31
32
use std:: boxed:: Box ;
32
33
use wasmi_arena:: { Arena , ArenaIndex } ;
33
34
use wasmi_core:: TrapCode ;
34
- use wasmparser:: { FuncToValidate , ValidatorResources } ;
35
+ use wasmparser:: { FuncToValidate , ValidatorResources , WasmFeatures } ;
35
36
36
37
/// A reference to a compiled function stored in the [`CodeMap`] of an [`Engine`](crate::Engine).
37
38
#[ derive( Debug , Copy , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
@@ -102,16 +103,16 @@ impl InternalFuncEntity {
102
103
///
103
104
/// - If function translation failed.
104
105
/// - If `ctx` ran out of fuel in case fuel consumption is enabled.
105
- fn compile ( & mut self , fuel : Option < & mut Fuel > ) -> Result < ( ) , Error > {
106
+ fn compile ( & mut self , fuel : Option < & mut Fuel > , features : & WasmFeatures ) -> Result < ( ) , Error > {
106
107
let uncompiled = match self {
107
108
InternalFuncEntity :: Uncompiled ( func) => func,
108
109
InternalFuncEntity :: Compiled ( func) => {
109
110
unreachable ! ( "expected func to be uncompiled: {func:?}" )
110
111
}
111
112
} ;
112
- let func_idx = uncompiled. func_idx ;
113
+ let func_idx = uncompiled. func_index ;
113
114
let bytes = mem:: take ( & mut uncompiled. bytes ) ;
114
- let needs_validation = uncompiled. func_to_validate . is_some ( ) ;
115
+ let needs_validation = uncompiled. validation . is_some ( ) ;
115
116
let compilation_fuel = |_costs : & FuelCosts | {
116
117
let len_bytes = bytes. as_slice ( ) . len ( ) as u64 ;
117
118
let compile_factor = match needs_validation {
@@ -133,10 +134,16 @@ impl InternalFuncEntity {
133
134
module. engine( )
134
135
)
135
136
} ;
136
- match uncompiled. func_to_validate . take ( ) {
137
- Some ( func_to_validate ) => {
137
+ match uncompiled. validation . take ( ) {
138
+ Some ( ( type_index , resources ) ) => {
138
139
let allocs = engine. get_allocs ( ) ;
139
140
let translator = FuncTranslator :: new ( func_idx, module, allocs. 0 ) ?;
141
+ let func_to_validate = FuncToValidate {
142
+ resources,
143
+ index : func_idx. into_u32 ( ) ,
144
+ ty : type_index. 0 ,
145
+ features : * features,
146
+ } ;
140
147
let validator = func_to_validate. into_validator ( allocs. 1 ) ;
141
148
let translator = ValidatingFuncTranslator :: new ( validator, translator) ?;
142
149
let allocs = FuncTranslationDriver :: new ( 0 , & bytes[ ..] , translator) ?. translate (
@@ -163,8 +170,8 @@ impl InternalFuncEntity {
163
170
164
171
/// An internal uncompiled function entity.
165
172
pub struct UncompiledFuncEntity {
166
- /// The index of the function within the ` module` .
167
- func_idx : FuncIdx ,
173
+ /// The index of the function within the Wasm module.
174
+ func_index : FuncIdx ,
168
175
/// The Wasm binary bytes.
169
176
bytes : SmallByteSlice ,
170
177
/// The Wasm module of the Wasm function.
@@ -175,33 +182,48 @@ pub struct UncompiledFuncEntity {
175
182
/// Optional Wasm validation information.
176
183
///
177
184
/// This is `Some` if the [`UncompiledFuncEntity`] is to be validated upon compilation.
178
- func_to_validate : Option < FuncToValidate < ValidatorResources > > ,
185
+ validation : Option < ( TypeIndex , ValidatorResources ) > ,
179
186
}
180
187
188
+ /// A function type index into the Wasm module.
189
+ #[ derive( Debug , Copy , Clone ) ]
190
+ #[ repr( transparent) ]
191
+ pub struct TypeIndex ( u32 ) ;
192
+
181
193
impl UncompiledFuncEntity {
182
194
/// Creates a new [`UncompiledFuncEntity`].
183
195
pub fn new (
184
- func_idx : FuncIdx ,
196
+ func_index : FuncIdx ,
185
197
bytes : impl Into < SmallByteSlice > ,
186
198
module : ModuleHeader ,
187
199
func_to_validate : impl Into < Option < FuncToValidate < ValidatorResources > > > ,
188
200
) -> Self {
201
+ let validation = func_to_validate. into ( ) . map ( |func_to_validate| {
202
+ assert_eq ! (
203
+ func_to_validate. index,
204
+ func_index. into_u32( ) ,
205
+ "Wasmi function index ({}) does not match with Wasm validation function index ({})" ,
206
+ func_to_validate. index,
207
+ func_index. into_u32( ) ,
208
+ ) ;
209
+ ( TypeIndex ( func_to_validate. ty ) , func_to_validate. resources )
210
+ } ) ;
189
211
Self {
190
- func_idx ,
212
+ func_index ,
191
213
bytes : bytes. into ( ) ,
192
214
module,
193
- func_to_validate : func_to_validate . into ( ) ,
215
+ validation ,
194
216
}
195
217
}
196
218
}
197
219
198
220
impl fmt:: Debug for UncompiledFuncEntity {
199
221
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
200
222
f. debug_struct ( "UncompiledFuncEntity" )
201
- . field ( "func_idx" , & self . func_idx )
223
+ . field ( "func_idx" , & self . func_index )
202
224
. field ( "bytes" , & self . bytes )
203
225
. field ( "module" , & self . module )
204
- . field ( "validate" , & self . func_to_validate . is_some ( ) )
226
+ . field ( "validate" , & self . validation . is_some ( ) )
205
227
. finish ( )
206
228
}
207
229
}
@@ -233,7 +255,7 @@ impl Default for SmallByteSlice {
233
255
234
256
impl SmallByteSlice {
235
257
/// The maximum amount of bytes that can be stored inline.
236
- const MAX_INLINE_SIZE : usize = 30 ;
258
+ const MAX_INLINE_SIZE : usize = 22 ;
237
259
238
260
/// Returns the underlying slice of bytes.
239
261
#[ inline]
@@ -353,9 +375,10 @@ impl CompiledFuncEntity {
353
375
}
354
376
355
377
/// Datastructure to efficiently store information about compiled functions.
356
- #[ derive( Debug , Default ) ]
378
+ #[ derive( Debug ) ]
357
379
pub struct CodeMap {
358
380
funcs : Arena < CompiledFunc , FuncEntity > ,
381
+ features : WasmFeatures ,
359
382
}
360
383
361
384
/// Atomicly accessible [`CompilationPhase`].
@@ -639,6 +662,7 @@ impl FuncEntity {
639
662
pub fn compile_and_get (
640
663
& self ,
641
664
mut fuel : Option < & mut Fuel > ,
665
+ features : & WasmFeatures ,
642
666
) -> Result < & CompiledFuncEntity , Error > {
643
667
loop {
644
668
if let Some ( func) = self . get_compiled ( ) {
@@ -661,7 +685,7 @@ impl FuncEntity {
661
685
// Note: We need to use `take` because Rust doesn't know that this part of
662
686
// the loop is only executed once.
663
687
let fuel = fuel. take ( ) ;
664
- match func. compile ( fuel) {
688
+ match func. compile ( fuel, features ) {
665
689
Ok ( ( ) ) => {
666
690
self . phase
667
691
. set_compiled ( )
@@ -679,6 +703,14 @@ impl FuncEntity {
679
703
}
680
704
681
705
impl CodeMap {
706
+ /// Creates a new [`CodeMap`].
707
+ pub fn new ( config : & Config ) -> Self {
708
+ Self {
709
+ funcs : Arena :: default ( ) ,
710
+ features : config. wasm_features ( ) ,
711
+ }
712
+ }
713
+
682
714
/// Allocates a new uninitialized [`CompiledFunc`] to the [`CodeMap`].
683
715
///
684
716
/// # Note
@@ -739,7 +771,7 @@ impl CodeMap {
739
771
} ;
740
772
match func. get_compiled ( ) {
741
773
Some ( func) => Ok ( func) ,
742
- None => func. compile_and_get ( fuel) ,
774
+ None => func. compile_and_get ( fuel, & self . features ) ,
743
775
}
744
776
}
745
777
}
0 commit comments