Don't copy executable code into a CodeMemory (#3265)
* Don't copy executable code into a `CodeMemory` This commit moves a copy from compiled artifacts into a `CodeMemory`. In general this commit drastically changes the meaning of a `CodeMemory`. Previously it was an iteratively-pushed-on structure that would accumulate executable code over time. Afterwards, however, it's a manager for an `MmapVec` which updates the permissions on text section to ensure that the pages are executable. By taking ownership of an `MmapVec` within a `CodeMemory` there's no need to copy any data around, which means that the `.text` section in the ELF image produced by Wasmtime is usable as-is after placement in memory and relocations have been resolved. This moves Wasmtime one step closer to being able to directly use a module after it's `mmap`'d into memory, optimizing when a module is loaded. * Fix windows section alignment * Review comments
This commit is contained in:
@@ -732,7 +732,7 @@ impl<'a> Instantiator<'a> {
|
||||
.allocator()
|
||||
.allocate(InstanceAllocationRequest {
|
||||
module: compiled_module.module().clone(),
|
||||
image_base: compiled_module.code().range().0,
|
||||
image_base: compiled_module.code().as_ptr() as usize,
|
||||
functions: compiled_module.functions(),
|
||||
imports: self.cur.build(),
|
||||
shared_signatures: self.cur.module.signatures().as_module_map().into(),
|
||||
|
||||
@@ -44,7 +44,6 @@ impl ModuleRegistry {
|
||||
/// Registers a new module with the registry.
|
||||
pub fn register(&mut self, module: &Module) {
|
||||
let compiled_module = module.compiled_module();
|
||||
let (start, end) = compiled_module.code().range();
|
||||
|
||||
// If there's not actually any functions in this module then we may
|
||||
// still need to preserve it for its data segments. Instances of this
|
||||
@@ -59,8 +58,10 @@ impl ModuleRegistry {
|
||||
|
||||
// The module code range is exclusive for end, so make it inclusive as it
|
||||
// may be a valid PC value
|
||||
assert!(start < end);
|
||||
let end = end - 1;
|
||||
let code = compiled_module.code();
|
||||
assert!(!code.is_empty());
|
||||
let start = code.as_ptr() as usize;
|
||||
let end = start + code.len() - 1;
|
||||
|
||||
// Ensure the module isn't already present in the registry
|
||||
// This is expected when a module is instantiated multiple times in the
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::any::Any;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::sync::Arc;
|
||||
use wasmtime_environ::{EntityIndex, Module, ModuleType, PrimaryMap, SignatureIndex};
|
||||
use wasmtime_jit::CodeMemory;
|
||||
use wasmtime_jit::{CodeMemory, MmapVec};
|
||||
use wasmtime_runtime::{
|
||||
Imports, InstanceAllocationRequest, InstanceAllocator, InstanceHandle,
|
||||
OnDemandInstanceAllocator, VMContext, VMFunctionBody, VMSharedSignatureIndex, VMTrampoline,
|
||||
@@ -82,20 +82,18 @@ pub fn create_function(
|
||||
stub_fn as usize,
|
||||
&mut obj,
|
||||
)?;
|
||||
let obj = obj.write()?;
|
||||
let obj = MmapVec::from_obj(obj)?;
|
||||
|
||||
// Copy the results of JIT compilation into executable memory, and this will
|
||||
// also take care of unwind table registration.
|
||||
let mut code_memory = CodeMemory::new();
|
||||
let (alloc, _obj) = code_memory.allocate_for_object_unparsed(&obj)?;
|
||||
let mut code_memory = CodeMemory::new(obj);
|
||||
let code = code_memory.publish()?;
|
||||
|
||||
// Extract the host/wasm trampolines from the results of compilation since
|
||||
// we know their start/length.
|
||||
let host_trampoline = alloc[t1.start as usize..][..t1.length as usize].as_ptr();
|
||||
let wasm_trampoline = &mut alloc[t2.start as usize..][..t2.length as usize];
|
||||
let wasm_trampoline = wasm_trampoline as *mut [u8] as *mut [VMFunctionBody];
|
||||
|
||||
code_memory.publish();
|
||||
let host_trampoline = code.text[t1.start as usize..][..t1.length as usize].as_ptr();
|
||||
let wasm_trampoline = &code.text[t2.start as usize..][..t2.length as usize];
|
||||
let wasm_trampoline = wasm_trampoline as *const [u8] as *mut [VMFunctionBody];
|
||||
|
||||
let sig = engine.signatures().register(ft.as_wasm_func_type());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user