@@ -11,6 +11,10 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
11
11
use cranelift_wasm:: ModuleTranslationState ;
12
12
use std:: collections:: HashMap ;
13
13
use std:: convert:: TryFrom ;
14
+ use std:: sync:: {
15
+ atomic:: { AtomicPtr , Ordering } ,
16
+ RwLock ,
17
+ } ;
14
18
use wasmtime_debug:: { emit_debugsections_image, DebugInfoData } ;
15
19
use wasmtime_environ:: entity:: { EntityRef , PrimaryMap } ;
16
20
use wasmtime_environ:: isa:: { TargetFrontendConfig , TargetIsa } ;
@@ -51,13 +55,16 @@ pub enum CompilationStrategy {
51
55
pub struct Compiler {
52
56
isa : Box < dyn TargetIsa > ,
53
57
54
- code_memory : CodeMemory ,
55
58
trap_registry : TrapRegistry ,
56
- trampoline_park : HashMap < VMSharedSignatureIndex , * const VMFunctionBody > ,
57
59
signatures : SignatureRegistry ,
58
60
strategy : CompilationStrategy ,
59
61
cache_config : CacheConfig ,
62
+ inner : RwLock < CompilerInner > ,
63
+ }
60
64
65
+ struct CompilerInner {
66
+ code_memory : CodeMemory ,
67
+ trampoline_park : HashMap < VMSharedSignatureIndex , AtomicPtr < VMFunctionBody > > ,
61
68
/// The `FunctionBuilderContext`, shared between trampline function compilations.
62
69
fn_builder_ctx : FunctionBuilderContext ,
63
70
}
@@ -71,13 +78,15 @@ impl Compiler {
71
78
) -> Self {
72
79
Self {
73
80
isa,
74
- code_memory : CodeMemory :: new ( ) ,
75
- trampoline_park : HashMap :: new ( ) ,
76
81
signatures : SignatureRegistry :: new ( ) ,
77
- fn_builder_ctx : FunctionBuilderContext :: new ( ) ,
78
82
strategy,
79
83
trap_registry : TrapRegistry :: default ( ) ,
80
84
cache_config,
85
+ inner : RwLock :: new ( CompilerInner {
86
+ code_memory : CodeMemory :: new ( ) ,
87
+ trampoline_park : HashMap :: new ( ) ,
88
+ fn_builder_ctx : FunctionBuilderContext :: new ( ) ,
89
+ } ) ,
81
90
}
82
91
}
83
92
}
@@ -95,14 +104,14 @@ impl Compiler {
95
104
96
105
/// Compile the given function bodies.
97
106
pub ( crate ) fn compile < ' data > (
98
- & mut self ,
107
+ & self ,
99
108
module : & Module ,
100
109
module_translation : & ModuleTranslationState ,
101
110
function_body_inputs : PrimaryMap < DefinedFuncIndex , FunctionBodyData < ' data > > ,
102
111
debug_data : Option < DebugInfoData > ,
103
112
) -> Result <
104
113
(
105
- PrimaryMap < DefinedFuncIndex , * mut [ VMFunctionBody ] > ,
114
+ PrimaryMap < DefinedFuncIndex , * const [ VMFunctionBody ] > ,
106
115
PrimaryMap < DefinedFuncIndex , ir:: JumpTableOffsets > ,
107
116
Relocations ,
108
117
Option < Vec < u8 > > ,
@@ -138,8 +147,9 @@ impl Compiler {
138
147
}
139
148
. map_err ( SetupError :: Compile ) ?;
140
149
141
- let allocated_functions =
142
- allocate_functions ( & mut self . code_memory , & compilation) . map_err ( |message| {
150
+ let mut inner = self . inner . write ( ) . unwrap ( ) ;
151
+ let allocated_functions = allocate_functions ( & mut inner. code_memory , & compilation)
152
+ . map_err ( |message| {
143
153
SetupError :: Instantiate ( InstantiationError :: Resource ( format ! (
144
154
"failed to allocate memory for functions: {}" ,
145
155
message
@@ -201,48 +211,52 @@ impl Compiler {
201
211
202
212
/// Create a trampoline for invoking a function.
203
213
pub ( crate ) fn get_trampoline (
204
- & mut self ,
214
+ & self ,
205
215
signature : & ir:: Signature ,
206
216
value_size : usize ,
207
- ) -> Result < * const VMFunctionBody , SetupError > {
217
+ ) -> Result < * mut VMFunctionBody , SetupError > {
208
218
let index = self . signatures . register ( signature) ;
209
- if let Some ( trampoline) = self . trampoline_park . get ( & index) {
210
- return Ok ( * trampoline) ;
219
+ let inner = & mut * self . inner . write ( ) . unwrap ( ) ;
220
+ if let Some ( trampoline) = inner. trampoline_park . get ( & index) {
221
+ return Ok ( trampoline. load ( Ordering :: SeqCst ) ) ;
211
222
}
212
223
let body = make_trampoline (
213
224
& * self . isa ,
214
- & mut self . code_memory ,
215
- & mut self . fn_builder_ctx ,
225
+ & mut inner . code_memory ,
226
+ & mut inner . fn_builder_ctx ,
216
227
signature,
217
228
value_size,
218
229
) ?;
219
- self . trampoline_park . insert ( index, body) ;
230
+ inner . trampoline_park . insert ( index, AtomicPtr :: new ( body) ) ;
220
231
return Ok ( body) ;
221
232
}
222
233
223
234
/// Create and publish a trampoline for invoking a function.
224
235
pub fn get_published_trampoline (
225
- & mut self ,
236
+ & self ,
226
237
signature : & ir:: Signature ,
227
238
value_size : usize ,
228
- ) -> Result < * const VMFunctionBody , SetupError > {
239
+ ) -> Result < * mut VMFunctionBody , SetupError > {
229
240
let result = self . get_trampoline ( signature, value_size) ?;
230
241
self . publish_compiled_code ( ) ;
231
242
Ok ( result)
232
243
}
233
244
234
245
/// Make memory containing compiled code executable.
235
- pub ( crate ) fn publish_compiled_code ( & mut self ) {
236
- self . code_memory . publish ( ) ;
246
+ pub ( crate ) fn publish_compiled_code ( & self ) {
247
+ self . inner . write ( ) . unwrap ( ) . code_memory . publish ( ) ;
237
248
}
238
249
239
250
pub ( crate ) fn profiler_module_load (
240
- & mut self ,
251
+ & self ,
241
252
profiler : & mut Box < dyn ProfilingAgent + Send > ,
242
253
module_name : & str ,
243
254
dbg_image : Option < & [ u8 ] > ,
244
255
) -> ( ) {
245
- self . code_memory
256
+ self . inner
257
+ . write ( )
258
+ . unwrap ( )
259
+ . code_memory
246
260
. profiler_module_load ( profiler, module_name, dbg_image) ;
247
261
}
248
262
@@ -264,7 +278,7 @@ fn make_trampoline(
264
278
fn_builder_ctx : & mut FunctionBuilderContext ,
265
279
signature : & ir:: Signature ,
266
280
value_size : usize ,
267
- ) -> Result < * const VMFunctionBody , SetupError > {
281
+ ) -> Result < * mut VMFunctionBody , SetupError > {
268
282
let pointer_type = isa. pointer_type ( ) ;
269
283
let mut wrapper_sig = ir:: Signature :: new ( isa. frontend_config ( ) . default_call_conv ) ;
270
284
@@ -373,26 +387,26 @@ fn make_trampoline(
373
387
unwind_info,
374
388
} )
375
389
. map_err ( |message| SetupError :: Instantiate ( InstantiationError :: Resource ( message) ) ) ?
376
- . as_ptr ( ) )
390
+ . as_mut_ptr ( ) )
377
391
}
378
392
379
393
fn allocate_functions (
380
394
code_memory : & mut CodeMemory ,
381
395
compilation : & Compilation ,
382
- ) -> Result < PrimaryMap < DefinedFuncIndex , * mut [ VMFunctionBody ] > , String > {
396
+ ) -> Result < PrimaryMap < DefinedFuncIndex , * const [ VMFunctionBody ] > , String > {
383
397
let fat_ptrs = code_memory. allocate_for_compilation ( compilation) ?;
384
398
385
399
// Second, create a PrimaryMap from result vector of pointers.
386
400
let mut result = PrimaryMap :: with_capacity ( compilation. len ( ) ) ;
387
401
for i in 0 ..fat_ptrs. len ( ) {
388
- let fat_ptr: * mut [ VMFunctionBody ] = fat_ptrs[ i] ;
402
+ let fat_ptr: * const [ VMFunctionBody ] = fat_ptrs[ i] ;
389
403
result. push ( fat_ptr) ;
390
404
}
391
405
Ok ( result)
392
406
}
393
407
394
408
fn register_traps (
395
- allocated_functions : & PrimaryMap < DefinedFuncIndex , * mut [ VMFunctionBody ] > ,
409
+ allocated_functions : & PrimaryMap < DefinedFuncIndex , * const [ VMFunctionBody ] > ,
396
410
traps : & Traps ,
397
411
registry : & TrapRegistry ,
398
412
) -> TrapRegistration {
0 commit comments