Skip to content

Commit 5a575cd

Browse files
authored
Merge branch 'master' into feature/preopen-fd-and-more
2 parents b4ded07 + f959c3f commit 5a575cd

File tree

11 files changed

+128
-65
lines changed

11 files changed

+128
-65
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Blocks of changes will separated by version increments.
66

77
## **[Unreleased]**
88
- [#343](https://github.com/wasmerio/wasmer/pull/343) Implement preopened files for WASI and fix aligment issue when accessing WASI memory
9+
- [#367](https://github.com/wasmerio/wasmer/pull/367) Add caching support to the LLVM backend.
910
- [#366](https://github.com/wasmerio/wasmer/pull/366) Remove `UserTrapper` trait to fix [#365](https://github.com/wasmerio/wasmer/issues/365).
1011
- [#348](https://github.com/wasmerio/wasmer/pull/348) Refactor internal runtime ↔️ backend abstraction.
1112
- [#355](https://github.com/wasmerio/wasmer/pull/355) Misc changes to `Cargo.toml`s for publishing

lib/clif-backend/src/cache.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,12 @@ impl CacheGenerator {
2727
}
2828

2929
impl CacheGen for CacheGenerator {
30-
fn generate_cache(
31-
&self,
32-
module: &ModuleInner,
33-
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), Error> {
34-
let info = Box::new(module.info.clone());
35-
30+
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), Error> {
3631
// Clone the memory to a new location. This could take a long time,
3732
// depending on the throughput of your memcpy implementation.
3833
let compiled_code = (*self.memory).clone();
3934

4035
Ok((
41-
info,
4236
self.backend_cache.into_backend_data()?.into_boxed_slice(),
4337
compiled_code,
4438
))

lib/llvm-backend/cpp/object_loader.cpp

+16-11
Original file line numberDiff line numberDiff line change
@@ -175,21 +175,26 @@ WasmModule::WasmModule(
175175
callbacks_t callbacks
176176
) : memory_manager(std::unique_ptr<MemoryManager>(new MemoryManager(callbacks)))
177177
{
178-
object_file = llvm::cantFail(llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef(
179-
llvm::StringRef((const char *)object_start, object_size), "object"
180-
)));
178+
181179

182-
SymbolLookup symbol_resolver(callbacks);
183-
runtime_dyld = std::unique_ptr<llvm::RuntimeDyld>(new llvm::RuntimeDyld(*memory_manager, symbol_resolver));
180+
if (auto created_object_file = llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef(
181+
llvm::StringRef((const char *)object_start, object_size), "object"
182+
))) {
183+
object_file = cantFail(std::move(created_object_file));
184+
SymbolLookup symbol_resolver(callbacks);
185+
runtime_dyld = std::unique_ptr<llvm::RuntimeDyld>(new llvm::RuntimeDyld(*memory_manager, symbol_resolver));
184186

185-
runtime_dyld->setProcessAllSections(true);
187+
runtime_dyld->setProcessAllSections(true);
186188

187-
runtime_dyld->loadObject(*object_file);
188-
runtime_dyld->finalizeWithMemoryManagerLocking();
189+
runtime_dyld->loadObject(*object_file);
190+
runtime_dyld->finalizeWithMemoryManagerLocking();
189191

190-
if (runtime_dyld->hasError()) {
191-
std::cout << "RuntimeDyld error: " << (std::string)runtime_dyld->getErrorString() << std::endl;
192-
abort();
192+
if (runtime_dyld->hasError()) {
193+
_init_failed = true;
194+
return;
195+
}
196+
} else {
197+
_init_failed = true;
193198
}
194199
}
195200

lib/llvm-backend/cpp/object_loader.hh

+5
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ struct WasmModule
152152

153153
void *get_func(llvm::StringRef name) const;
154154

155+
bool _init_failed = false;
155156
private:
156157
std::unique_ptr<llvm::RuntimeDyld::MemoryManager> memory_manager;
157158
std::unique_ptr<llvm::object::ObjectFile> object_file;
@@ -164,6 +165,10 @@ extern "C"
164165
{
165166
*module_out = new WasmModule(mem_ptr, mem_size, callbacks);
166167

168+
if ((*module_out)->_init_failed) {
169+
return RESULT_OBJECT_LOAD_FAILURE;
170+
}
171+
167172
return RESULT_OK;
168173
}
169174

lib/llvm-backend/src/backend.rs

+83-7
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@ use std::{
1313
any::Any,
1414
ffi::{c_void, CString},
1515
mem,
16+
ops::Deref,
1617
ptr::{self, NonNull},
1718
slice, str,
18-
sync::Once,
19+
sync::{Arc, Once},
1920
};
2021
use wasmer_runtime_core::{
21-
backend::RunnableModule,
22+
backend::{
23+
sys::{Memory, Protect},
24+
CacheGen, RunnableModule,
25+
},
26+
cache::Error as CacheError,
2227
module::ModuleInfo,
2328
structures::TypedIndex,
2429
typed_func::{Wasm, WasmTrapInfo},
@@ -203,17 +208,32 @@ fn get_callbacks() -> Callbacks {
203208
}
204209
}
205210

211+
pub enum Buffer {
212+
LlvmMemory(MemoryBuffer),
213+
Memory(Memory),
214+
}
215+
216+
impl Deref for Buffer {
217+
type Target = [u8];
218+
fn deref(&self) -> &[u8] {
219+
match self {
220+
Buffer::LlvmMemory(mem_buffer) => mem_buffer.as_slice(),
221+
Buffer::Memory(memory) => unsafe { memory.as_slice() },
222+
}
223+
}
224+
}
225+
206226
unsafe impl Send for LLVMBackend {}
207227
unsafe impl Sync for LLVMBackend {}
208228

209229
pub struct LLVMBackend {
210230
module: *mut LLVMModule,
211231
#[allow(dead_code)]
212-
memory_buffer: MemoryBuffer,
232+
buffer: Arc<Buffer>,
213233
}
214234

215235
impl LLVMBackend {
216-
pub fn new(module: Module, _intrinsics: Intrinsics) -> Self {
236+
pub fn new(module: Module, _intrinsics: Intrinsics) -> (Self, LLVMCache) {
217237
Target::initialize_x86(&InitializationConfig {
218238
asm_parser: true,
219239
asm_printer: true,
@@ -262,10 +282,44 @@ impl LLVMBackend {
262282
panic!("failed to load object")
263283
}
264284

265-
Self {
266-
module,
267-
memory_buffer,
285+
let buffer = Arc::new(Buffer::LlvmMemory(memory_buffer));
286+
287+
(
288+
Self {
289+
module,
290+
buffer: Arc::clone(&buffer),
291+
},
292+
LLVMCache { buffer },
293+
)
294+
}
295+
296+
pub unsafe fn from_buffer(memory: Memory) -> Result<(Self, LLVMCache), String> {
297+
let callbacks = get_callbacks();
298+
let mut module: *mut LLVMModule = ptr::null_mut();
299+
300+
let slice = unsafe { memory.as_slice() };
301+
302+
let res = module_load(slice.as_ptr(), slice.len(), callbacks, &mut module);
303+
304+
if res != LLVMResult::OK {
305+
return Err("failed to load object".to_string());
268306
}
307+
308+
static SIGNAL_HANDLER_INSTALLED: Once = Once::new();
309+
310+
SIGNAL_HANDLER_INSTALLED.call_once(|| unsafe {
311+
crate::platform::install_signal_handler();
312+
});
313+
314+
let buffer = Arc::new(Buffer::Memory(memory));
315+
316+
Ok((
317+
Self {
318+
module,
319+
buffer: Arc::clone(&buffer),
320+
},
321+
LLVMCache { buffer },
322+
))
269323
}
270324
}
271325

@@ -322,6 +376,28 @@ impl RunnableModule for LLVMBackend {
322376
}
323377
}
324378

379+
unsafe impl Send for LLVMCache {}
380+
unsafe impl Sync for LLVMCache {}
381+
382+
pub struct LLVMCache {
383+
buffer: Arc<Buffer>,
384+
}
385+
386+
impl CacheGen for LLVMCache {
387+
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), CacheError> {
388+
let mut memory = Memory::with_size_protect(self.buffer.len(), Protect::ReadWrite)
389+
.map_err(CacheError::SerializeError)?;
390+
391+
let buffer = self.buffer.deref();
392+
393+
unsafe {
394+
memory.as_slice_mut()[..buffer.len()].copy_from_slice(buffer);
395+
}
396+
397+
Ok(([].as_ref().into(), memory))
398+
}
399+
}
400+
325401
#[cfg(feature = "disasm")]
326402
unsafe fn disass_ptr(ptr: *const u8, size: usize, inst_count: usize) {
327403
use capstone::arch::BuildsCapstone;

lib/llvm-backend/src/lib.rs

+13-24
Original file line numberDiff line numberDiff line change
@@ -38,39 +38,28 @@ impl Compiler for LLVMCompiler {
3838
let (info, code_reader) = read_info::read_module(wasm, compiler_config).unwrap();
3939
let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap();
4040

41-
let backend = backend::LLVMBackend::new(module, intrinsics);
41+
let (backend, cache_gen) = backend::LLVMBackend::new(module, intrinsics);
4242

43-
// Create placeholder values here.
44-
let cache_gen = {
45-
use wasmer_runtime_core::backend::{sys::Memory, CacheGen};
46-
use wasmer_runtime_core::cache::Error as CacheError;
47-
use wasmer_runtime_core::module::ModuleInfo;
48-
49-
struct Placeholder;
43+
Ok(ModuleInner {
44+
runnable_module: Box::new(backend),
45+
cache_gen: Box::new(cache_gen),
5046

51-
impl CacheGen for Placeholder {
52-
fn generate_cache(
53-
&self,
54-
_module: &ModuleInner,
55-
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError> {
56-
unimplemented!()
57-
}
58-
}
47+
info,
48+
})
49+
}
5950

60-
Box::new(Placeholder)
61-
};
51+
unsafe fn from_cache(&self, artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
52+
let (info, _, memory) = artifact.consume();
53+
let (backend, cache_gen) =
54+
backend::LLVMBackend::from_buffer(memory).map_err(CacheError::DeserializeError)?;
6255

6356
Ok(ModuleInner {
6457
runnable_module: Box::new(backend),
65-
cache_gen,
58+
cache_gen: Box::new(cache_gen),
6659

6760
info,
6861
})
6962
}
70-
71-
unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
72-
unimplemented!("the llvm backend doesn't support caching yet")
73-
}
7463
}
7564

7665
fn validate(bytes: &[u8]) -> Result<(), CompileError> {
@@ -123,7 +112,7 @@ fn test_read_module() {
123112

124113
let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap();
125114

126-
let backend = backend::LLVMBackend::new(module, intrinsics);
115+
let (backend, _) = backend::LLVMBackend::new(module, intrinsics);
127116

128117
let func_ptr = backend.get_func(&info, LocalFuncIndex::new(0)).unwrap();
129118

lib/runtime-core/src/backend.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,5 @@ pub trait RunnableModule: Send + Sync {
8383
}
8484

8585
pub trait CacheGen: Send + Sync {
86-
fn generate_cache(
87-
&self,
88-
module: &ModuleInner,
89-
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError>;
86+
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), CacheError>;
9087
}

lib/runtime-core/src/module.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,12 @@ impl Module {
121121
}
122122

123123
pub fn cache(&self) -> Result<Artifact, CacheError> {
124-
let (info, backend_metadata, code) = self.inner.cache_gen.generate_cache(&self.inner)?;
125-
Ok(Artifact::from_parts(info, backend_metadata, code))
124+
let (backend_metadata, code) = self.inner.cache_gen.generate_cache()?;
125+
Ok(Artifact::from_parts(
126+
Box::new(self.inner.info.clone()),
127+
backend_metadata,
128+
code,
129+
))
126130
}
127131

128132
pub fn info(&self) -> &ModuleInfo {

lib/runtime-core/src/vm.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -569,10 +569,7 @@ mod vm_ctx_tests {
569569
}
570570
}
571571
impl CacheGen for Placeholder {
572-
fn generate_cache(
573-
&self,
574-
module: &ModuleInner,
575-
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError> {
572+
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), CacheError> {
576573
unimplemented!()
577574
}
578575
}

lib/runtime/examples/call.rs

-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ static WAT: &'static str = r#"
77
(type (;0;) (func (result i32)))
88
(import "env" "do_panic" (func $do_panic (type 0)))
99
(func $dbz (result i32)
10-
call $do_panic
11-
drop
1210
i32.const 42
1311
i32.const 0
1412
i32.div_u

lib/singlepass-backend/src/lib.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ use wasmer_runtime_core::{
3636

3737
struct Placeholder;
3838
impl CacheGen for Placeholder {
39-
fn generate_cache(
40-
&self,
41-
_module: &ModuleInner,
42-
) -> Result<(Box<ModuleInfo>, Box<[u8]>, Memory), CacheError> {
39+
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), CacheError> {
4340
Err(CacheError::Unknown(
4441
"the singlepass backend doesn't support caching yet".to_string(),
4542
))

0 commit comments

Comments
 (0)