Skip to content

Commit 4cb84fc

Browse files
authored
Merge pull request #1 from paritytech/a-thread-safe-api
A thread safe api
2 parents 8acfdbd + 851887d commit 4cb84fc

File tree

12 files changed

+98
-72
lines changed

12 files changed

+98
-72
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/api/src/callable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl WrappedCallable for WasmtimeFn {
158158
// Get the trampoline to call for this function.
159159
let exec_code_buf = self
160160
.store
161-
.compiler_mut()
161+
.compiler()
162162
.get_published_trampoline(&signature, value_size)
163163
.map_err(|e| Trap::new(format!("trampoline error: {:?}", e)))?;
164164

crates/api/src/module.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ impl Module {
250250

251251
unsafe fn compile(store: &Store, binary: &[u8]) -> Result<Self> {
252252
let compiled = CompiledModule::new(
253-
&mut store.compiler_mut(),
253+
store.compiler(),
254254
binary,
255255
store.engine().config().debug_info,
256256
store.engine().config().profiler.as_ref(),

crates/api/src/runtime.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use anyhow::Result;
2-
use std::cell::RefCell;
32
use std::fmt;
43
use std::path::Path;
5-
use std::rc::Rc;
64
use std::sync::{Arc, Mutex};
75
use wasmparser::{OperatorValidatorConfig, ValidatingParserConfig};
86
use wasmtime_environ::settings::{self, Configurable};
@@ -447,12 +445,12 @@ impl Engine {
447445
#[derive(Clone)]
448446
pub struct Store {
449447
// FIXME(#777) should be `Arc` and this type should be thread-safe
450-
inner: Rc<StoreInner>,
448+
inner: Arc<StoreInner>,
451449
}
452450

453451
struct StoreInner {
454452
engine: Engine,
455-
compiler: RefCell<Compiler>,
453+
compiler: Compiler,
456454
}
457455

458456
impl Store {
@@ -465,9 +463,9 @@ impl Store {
465463
engine.config.cache_config.clone(),
466464
);
467465
Store {
468-
inner: Rc::new(StoreInner {
466+
inner: Arc::new(StoreInner {
469467
engine: engine.clone(),
470-
compiler: RefCell::new(compiler),
468+
compiler,
471469
}),
472470
}
473471
}
@@ -477,12 +475,8 @@ impl Store {
477475
&self.inner.engine
478476
}
479477

480-
pub(crate) fn compiler(&self) -> std::cell::Ref<'_, Compiler> {
481-
self.inner.compiler.borrow()
482-
}
483-
484-
pub(crate) fn compiler_mut(&self) -> std::cell::RefMut<'_, Compiler> {
485-
self.inner.compiler.borrow_mut()
478+
pub(crate) fn compiler(&self) -> &Compiler {
479+
&self.inner.compiler
486480
}
487481

488482
/// Returns whether the stores `a` and `b` refer to the same underlying
@@ -492,7 +486,7 @@ impl Store {
492486
/// to the same underlying storage, and this method can be used to determine
493487
/// whether two stores are indeed the same.
494488
pub fn same(a: &Store, b: &Store) -> bool {
495-
Rc::ptr_eq(&a.inner, &b.inner)
489+
Arc::ptr_eq(&a.inner, &b.inner)
496490
}
497491
}
498492

crates/api/src/trampoline/create_handle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use wasmtime_runtime::{Imports, InstanceHandle, VMFunctionBody};
1313
pub(crate) fn create_handle(
1414
module: Module,
1515
store: &Store,
16-
finished_functions: PrimaryMap<DefinedFuncIndex, *mut [VMFunctionBody]>,
16+
finished_functions: PrimaryMap<DefinedFuncIndex, *const [VMFunctionBody]>,
1717
state: Box<dyn Any>,
1818
) -> Result<InstanceHandle> {
1919
let imports = Imports::new(

crates/api/src/trampoline/func.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ pub fn create_handle_with_function(
264264

265265
let mut fn_builder_ctx = FunctionBuilderContext::new();
266266
let mut module = Module::new();
267-
let mut finished_functions: PrimaryMap<DefinedFuncIndex, *mut [VMFunctionBody]> =
267+
let mut finished_functions: PrimaryMap<DefinedFuncIndex, *const [VMFunctionBody]> =
268268
PrimaryMap::new();
269269
let mut code_memory = CodeMemory::new();
270270

@@ -296,7 +296,7 @@ pub fn create_handle_with_function(
296296

297297
pub unsafe fn create_handle_with_raw_function(
298298
ft: &FuncType,
299-
func: *mut [VMFunctionBody],
299+
func: *const [VMFunctionBody],
300300
store: &Store,
301301
state: Box<dyn Any>,
302302
) -> Result<InstanceHandle> {

crates/jit/src/compiler.rs

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
1111
use cranelift_wasm::ModuleTranslationState;
1212
use std::collections::HashMap;
1313
use std::convert::TryFrom;
14+
use std::sync::{
15+
atomic::{AtomicPtr, Ordering},
16+
RwLock,
17+
};
1418
use wasmtime_debug::{emit_debugsections_image, DebugInfoData};
1519
use wasmtime_environ::entity::{EntityRef, PrimaryMap};
1620
use wasmtime_environ::isa::{TargetFrontendConfig, TargetIsa};
@@ -51,13 +55,16 @@ pub enum CompilationStrategy {
5155
pub struct Compiler {
5256
isa: Box<dyn TargetIsa>,
5357

54-
code_memory: CodeMemory,
5558
trap_registry: TrapRegistry,
56-
trampoline_park: HashMap<VMSharedSignatureIndex, *const VMFunctionBody>,
5759
signatures: SignatureRegistry,
5860
strategy: CompilationStrategy,
5961
cache_config: CacheConfig,
62+
inner: RwLock<CompilerInner>,
63+
}
6064

65+
struct CompilerInner {
66+
code_memory: CodeMemory,
67+
trampoline_park: HashMap<VMSharedSignatureIndex, AtomicPtr<VMFunctionBody>>,
6168
/// The `FunctionBuilderContext`, shared between trampline function compilations.
6269
fn_builder_ctx: FunctionBuilderContext,
6370
}
@@ -71,13 +78,15 @@ impl Compiler {
7178
) -> Self {
7279
Self {
7380
isa,
74-
code_memory: CodeMemory::new(),
75-
trampoline_park: HashMap::new(),
7681
signatures: SignatureRegistry::new(),
77-
fn_builder_ctx: FunctionBuilderContext::new(),
7882
strategy,
7983
trap_registry: TrapRegistry::default(),
8084
cache_config,
85+
inner: RwLock::new(CompilerInner {
86+
code_memory: CodeMemory::new(),
87+
trampoline_park: HashMap::new(),
88+
fn_builder_ctx: FunctionBuilderContext::new(),
89+
}),
8190
}
8291
}
8392
}
@@ -95,14 +104,14 @@ impl Compiler {
95104

96105
/// Compile the given function bodies.
97106
pub(crate) fn compile<'data>(
98-
&mut self,
107+
&self,
99108
module: &Module,
100109
module_translation: &ModuleTranslationState,
101110
function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
102111
debug_data: Option<DebugInfoData>,
103112
) -> Result<
104113
(
105-
PrimaryMap<DefinedFuncIndex, *mut [VMFunctionBody]>,
114+
PrimaryMap<DefinedFuncIndex, *const [VMFunctionBody]>,
106115
PrimaryMap<DefinedFuncIndex, ir::JumpTableOffsets>,
107116
Relocations,
108117
Option<Vec<u8>>,
@@ -138,8 +147,9 @@ impl Compiler {
138147
}
139148
.map_err(SetupError::Compile)?;
140149

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| {
143153
SetupError::Instantiate(InstantiationError::Resource(format!(
144154
"failed to allocate memory for functions: {}",
145155
message
@@ -201,48 +211,52 @@ impl Compiler {
201211

202212
/// Create a trampoline for invoking a function.
203213
pub(crate) fn get_trampoline(
204-
&mut self,
214+
&self,
205215
signature: &ir::Signature,
206216
value_size: usize,
207-
) -> Result<*const VMFunctionBody, SetupError> {
217+
) -> Result<*mut VMFunctionBody, SetupError> {
208218
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));
211222
}
212223
let body = make_trampoline(
213224
&*self.isa,
214-
&mut self.code_memory,
215-
&mut self.fn_builder_ctx,
225+
&mut inner.code_memory,
226+
&mut inner.fn_builder_ctx,
216227
signature,
217228
value_size,
218229
)?;
219-
self.trampoline_park.insert(index, body);
230+
inner.trampoline_park.insert(index, AtomicPtr::new(body));
220231
return Ok(body);
221232
}
222233

223234
/// Create and publish a trampoline for invoking a function.
224235
pub fn get_published_trampoline(
225-
&mut self,
236+
&self,
226237
signature: &ir::Signature,
227238
value_size: usize,
228-
) -> Result<*const VMFunctionBody, SetupError> {
239+
) -> Result<*mut VMFunctionBody, SetupError> {
229240
let result = self.get_trampoline(signature, value_size)?;
230241
self.publish_compiled_code();
231242
Ok(result)
232243
}
233244

234245
/// 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();
237248
}
238249

239250
pub(crate) fn profiler_module_load(
240-
&mut self,
251+
&self,
241252
profiler: &mut Box<dyn ProfilingAgent + Send>,
242253
module_name: &str,
243254
dbg_image: Option<&[u8]>,
244255
) -> () {
245-
self.code_memory
256+
self.inner
257+
.write()
258+
.unwrap()
259+
.code_memory
246260
.profiler_module_load(profiler, module_name, dbg_image);
247261
}
248262

@@ -264,7 +278,7 @@ fn make_trampoline(
264278
fn_builder_ctx: &mut FunctionBuilderContext,
265279
signature: &ir::Signature,
266280
value_size: usize,
267-
) -> Result<*const VMFunctionBody, SetupError> {
281+
) -> Result<*mut VMFunctionBody, SetupError> {
268282
let pointer_type = isa.pointer_type();
269283
let mut wrapper_sig = ir::Signature::new(isa.frontend_config().default_call_conv);
270284

@@ -373,26 +387,26 @@ fn make_trampoline(
373387
unwind_info,
374388
})
375389
.map_err(|message| SetupError::Instantiate(InstantiationError::Resource(message)))?
376-
.as_ptr())
390+
.as_mut_ptr())
377391
}
378392

379393
fn allocate_functions(
380394
code_memory: &mut CodeMemory,
381395
compilation: &Compilation,
382-
) -> Result<PrimaryMap<DefinedFuncIndex, *mut [VMFunctionBody]>, String> {
396+
) -> Result<PrimaryMap<DefinedFuncIndex, *const [VMFunctionBody]>, String> {
383397
let fat_ptrs = code_memory.allocate_for_compilation(compilation)?;
384398

385399
// Second, create a PrimaryMap from result vector of pointers.
386400
let mut result = PrimaryMap::with_capacity(compilation.len());
387401
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];
389403
result.push(fat_ptr);
390404
}
391405
Ok(result)
392406
}
393407

394408
fn register_traps(
395-
allocated_functions: &PrimaryMap<DefinedFuncIndex, *mut [VMFunctionBody]>,
409+
allocated_functions: &PrimaryMap<DefinedFuncIndex, *const [VMFunctionBody]>,
396410
traps: &Traps,
397411
registry: &TrapRegistry,
398412
) -> TrapRegistration {

0 commit comments

Comments
 (0)