Expose some more internals publicly (#340)
This commit is contained in:
committed by
Sergei Pepyakin
parent
f27e0ad53c
commit
71dd73d672
@@ -1,83 +0,0 @@
|
|||||||
//! Memory management for executable code.
|
|
||||||
// Copy of wasmtime's wasmtime-jit/src/code_memory.rs
|
|
||||||
|
|
||||||
use core::{cmp, mem};
|
|
||||||
use region;
|
|
||||||
use std::string::String;
|
|
||||||
use std::vec::Vec;
|
|
||||||
use wasmtime_runtime::{Mmap, VMFunctionBody};
|
|
||||||
|
|
||||||
/// Memory manager for executable code.
|
|
||||||
pub(crate) struct CodeMemory {
|
|
||||||
current: Mmap,
|
|
||||||
mmaps: Vec<Mmap>,
|
|
||||||
position: usize,
|
|
||||||
published: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CodeMemory {
|
|
||||||
/// Create a new `CodeMemory` instance.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
current: Mmap::new(),
|
|
||||||
mmaps: Vec::new(),
|
|
||||||
position: 0,
|
|
||||||
published: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allocate `size` bytes of memory which can be made executable later by
|
|
||||||
/// calling `publish()`. Note that we allocate the memory as writeable so
|
|
||||||
/// that it can be written to and patched, though we make it readonly before
|
|
||||||
/// actually executing from it.
|
|
||||||
///
|
|
||||||
/// TODO: Add an alignment flag.
|
|
||||||
fn allocate(&mut self, size: usize) -> Result<&mut [u8], String> {
|
|
||||||
if self.current.len() - self.position < size {
|
|
||||||
self.mmaps.push(mem::replace(
|
|
||||||
&mut self.current,
|
|
||||||
Mmap::with_at_least(cmp::max(0x10000, size))?,
|
|
||||||
));
|
|
||||||
self.position = 0;
|
|
||||||
}
|
|
||||||
let old_position = self.position;
|
|
||||||
self.position += size;
|
|
||||||
Ok(&mut self.current.as_mut_slice()[old_position..self.position])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert mut a slice from u8 to VMFunctionBody.
|
|
||||||
fn view_as_mut_vmfunc_slice(slice: &mut [u8]) -> &mut [VMFunctionBody] {
|
|
||||||
let byte_ptr: *mut [u8] = slice;
|
|
||||||
let body_ptr = byte_ptr as *mut [VMFunctionBody];
|
|
||||||
unsafe { &mut *body_ptr }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allocate enough memory to hold a copy of `slice` and copy the data into it.
|
|
||||||
/// TODO: Reorganize the code that calls this to emit code directly into the
|
|
||||||
/// mmap region rather than into a Vec that we need to copy in.
|
|
||||||
pub fn allocate_copy_of_byte_slice(
|
|
||||||
&mut self,
|
|
||||||
slice: &[u8],
|
|
||||||
) -> Result<&mut [VMFunctionBody], String> {
|
|
||||||
let new = self.allocate(slice.len())?;
|
|
||||||
new.copy_from_slice(slice);
|
|
||||||
Ok(Self::view_as_mut_vmfunc_slice(new))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make all allocated memory executable.
|
|
||||||
pub fn publish(&mut self) {
|
|
||||||
self.mmaps
|
|
||||||
.push(mem::replace(&mut self.current, Mmap::new()));
|
|
||||||
self.position = 0;
|
|
||||||
|
|
||||||
for m in &mut self.mmaps[self.published..] {
|
|
||||||
if m.len() != 0 {
|
|
||||||
unsafe {
|
|
||||||
region::protect(m.as_mut_ptr(), m.len(), region::Protection::ReadExecute)
|
|
||||||
}
|
|
||||||
.expect("unable to make memory readonly and executable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.published = self.mmaps.len();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,6 @@ extern crate alloc;
|
|||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::types::{PyAny, PyDict, PyTuple};
|
use pyo3::types::{PyAny, PyDict, PyTuple};
|
||||||
|
|
||||||
use crate::code_memory::CodeMemory;
|
|
||||||
use crate::function::Function;
|
use crate::function::Function;
|
||||||
use crate::memory::Memory;
|
use crate::memory::Memory;
|
||||||
use crate::value::{read_value_from, write_value_to};
|
use crate::value::{read_value_from, write_value_to};
|
||||||
@@ -18,6 +17,7 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
|||||||
use cranelift_wasm::{DefinedFuncIndex, FuncIndex};
|
use cranelift_wasm::{DefinedFuncIndex, FuncIndex};
|
||||||
use target_lexicon::HOST;
|
use target_lexicon::HOST;
|
||||||
use wasmtime_environ::{Export, Module};
|
use wasmtime_environ::{Export, Module};
|
||||||
|
use wasmtime_jit::CodeMemory;
|
||||||
use wasmtime_runtime::{Imports, InstanceHandle, VMContext, VMFunctionBody};
|
use wasmtime_runtime::{Imports, InstanceHandle, VMContext, VMFunctionBody};
|
||||||
|
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ use core::cell::RefCell;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use wasmtime_interface_types::ModuleData;
|
use wasmtime_interface_types::ModuleData;
|
||||||
|
|
||||||
mod code_memory;
|
|
||||||
mod function;
|
mod function;
|
||||||
mod import;
|
mod import;
|
||||||
mod instance;
|
mod instance;
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
//! Memory management for executable code.
|
|
||||||
// Copy of wasmtime's wasmtime-jit/src/code_memory.rs
|
|
||||||
|
|
||||||
use alloc::string::String;
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
use core::{cmp, mem};
|
|
||||||
use region;
|
|
||||||
use wasmtime_runtime::{Mmap, VMFunctionBody};
|
|
||||||
|
|
||||||
/// Memory manager for executable code.
|
|
||||||
pub(crate) struct CodeMemory {
|
|
||||||
current: Mmap,
|
|
||||||
mmaps: Vec<Mmap>,
|
|
||||||
position: usize,
|
|
||||||
published: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CodeMemory {
|
|
||||||
/// Create a new `CodeMemory` instance.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
current: Mmap::new(),
|
|
||||||
mmaps: Vec::new(),
|
|
||||||
position: 0,
|
|
||||||
published: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allocate `size` bytes of memory which can be made executable later by
|
|
||||||
/// calling `publish()`. Note that we allocate the memory as writeable so
|
|
||||||
/// that it can be written to and patched, though we make it readonly before
|
|
||||||
/// actually executing from it.
|
|
||||||
///
|
|
||||||
/// TODO: Add an alignment flag.
|
|
||||||
fn allocate(&mut self, size: usize) -> Result<&mut [u8], String> {
|
|
||||||
if self.current.len() - self.position < size {
|
|
||||||
self.mmaps.push(mem::replace(
|
|
||||||
&mut self.current,
|
|
||||||
Mmap::with_at_least(cmp::max(0x10000, size))?,
|
|
||||||
));
|
|
||||||
self.position = 0;
|
|
||||||
}
|
|
||||||
let old_position = self.position;
|
|
||||||
self.position += size;
|
|
||||||
Ok(&mut self.current.as_mut_slice()[old_position..self.position])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert mut a slice from u8 to VMFunctionBody.
|
|
||||||
fn view_as_mut_vmfunc_slice(slice: &mut [u8]) -> &mut [VMFunctionBody] {
|
|
||||||
let byte_ptr: *mut [u8] = slice;
|
|
||||||
let body_ptr = byte_ptr as *mut [VMFunctionBody];
|
|
||||||
unsafe { &mut *body_ptr }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allocate enough memory to hold a copy of `slice` and copy the data into it.
|
|
||||||
/// TODO: Reorganize the code that calls this to emit code directly into the
|
|
||||||
/// mmap region rather than into a Vec that we need to copy in.
|
|
||||||
pub fn allocate_copy_of_byte_slice(
|
|
||||||
&mut self,
|
|
||||||
slice: &[u8],
|
|
||||||
) -> Result<&mut [VMFunctionBody], String> {
|
|
||||||
let new = self.allocate(slice.len())?;
|
|
||||||
new.copy_from_slice(slice);
|
|
||||||
Ok(Self::view_as_mut_vmfunc_slice(new))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make all allocated memory executable.
|
|
||||||
pub fn publish(&mut self) {
|
|
||||||
self.mmaps
|
|
||||||
.push(mem::replace(&mut self.current, Mmap::new()));
|
|
||||||
self.position = 0;
|
|
||||||
|
|
||||||
for m in &mut self.mmaps[self.published..] {
|
|
||||||
if m.len() != 0 {
|
|
||||||
unsafe {
|
|
||||||
region::protect(m.as_mut_ptr(), m.len(), region::Protection::ReadExecute)
|
|
||||||
}
|
|
||||||
.expect("unable to make memory readonly and executable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.published = self.mmaps.len();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
//! Support for a calling of an imported function.
|
//! Support for a calling of an imported function.
|
||||||
|
|
||||||
use crate::r#ref::HostRef;
|
use crate::r#ref::HostRef;
|
||||||
use crate::trampoline::code_memory::CodeMemory;
|
|
||||||
use cranelift_codegen::ir::types;
|
use cranelift_codegen::ir::types;
|
||||||
use cranelift_codegen::ir::{InstBuilder, StackSlotData, StackSlotKind, TrapCode};
|
use cranelift_codegen::ir::{InstBuilder, StackSlotData, StackSlotKind, TrapCode};
|
||||||
use cranelift_codegen::Context;
|
use cranelift_codegen::Context;
|
||||||
@@ -12,6 +11,7 @@ use cranelift_wasm::{DefinedFuncIndex, FuncIndex};
|
|||||||
//use target_lexicon::HOST;
|
//use target_lexicon::HOST;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use wasmtime_environ::{Export, Module};
|
use wasmtime_environ::{Export, Module};
|
||||||
|
use wasmtime_jit::CodeMemory;
|
||||||
use wasmtime_runtime::{InstanceHandle, VMContext, VMFunctionBody};
|
use wasmtime_runtime::{InstanceHandle, VMContext, VMFunctionBody};
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
//! Utility module to create trampolines in/out WebAssembly module.
|
//! Utility module to create trampolines in/out WebAssembly module.
|
||||||
|
|
||||||
mod code_memory;
|
|
||||||
mod create_handle;
|
mod create_handle;
|
||||||
mod func;
|
mod func;
|
||||||
mod global;
|
mod global;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use region;
|
|||||||
use wasmtime_runtime::{Mmap, VMFunctionBody};
|
use wasmtime_runtime::{Mmap, VMFunctionBody};
|
||||||
|
|
||||||
/// Memory manager for executable code.
|
/// Memory manager for executable code.
|
||||||
pub(crate) struct CodeMemory {
|
pub struct CodeMemory {
|
||||||
current: Mmap,
|
current: Mmap,
|
||||||
mmaps: Vec<Mmap>,
|
mmaps: Vec<Mmap>,
|
||||||
position: usize,
|
position: usize,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::action::{get, inspect_memory, invoke};
|
use crate::action::{get, inspect_memory, invoke};
|
||||||
use crate::HashMap;
|
use crate::HashMap;
|
||||||
use crate::{
|
use crate::{
|
||||||
instantiate, ActionError, ActionOutcome, CompilationStrategy, Compiler, InstanceHandle,
|
instantiate, ActionError, ActionOutcome, CompilationStrategy, CompiledModule, Compiler,
|
||||||
Namespace, RuntimeValue, SetupError,
|
InstanceHandle, Namespace, RuntimeValue, SetupError,
|
||||||
};
|
};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
@@ -160,6 +160,20 @@ impl Context {
|
|||||||
Ok(instance)
|
Ok(instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compile a module.
|
||||||
|
pub fn compile_module(&mut self, data: &[u8]) -> Result<CompiledModule, SetupError> {
|
||||||
|
self.validate(&data).map_err(SetupError::Validate)?;
|
||||||
|
let debug_info = self.debug_info();
|
||||||
|
|
||||||
|
CompiledModule::new(
|
||||||
|
&mut *self.compiler,
|
||||||
|
data,
|
||||||
|
&mut self.namespace,
|
||||||
|
Rc::clone(&self.global_exports),
|
||||||
|
debug_info,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// If `name` isn't None, register it for the given instance.
|
/// If `name` isn't None, register it for the given instance.
|
||||||
pub fn optionally_name_instance(&mut self, name: Option<String>, instance: InstanceHandle) {
|
pub fn optionally_name_instance(&mut self, name: Option<String>, instance: InstanceHandle) {
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
|
|||||||
@@ -223,6 +223,16 @@ impl CompiledModule {
|
|||||||
Box::new(()),
|
Box::new(()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a reference-counting pointer to a module.
|
||||||
|
pub fn module(&self) -> Rc<Module> {
|
||||||
|
self.module.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a reference to a module.
|
||||||
|
pub fn module_ref(&self) -> &Module {
|
||||||
|
&self.module
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Similar to `DataInitializer`, but owns its own copy of the data rather
|
/// Similar to `DataInitializer`, but owns its own copy of the data rather
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ mod resolver;
|
|||||||
mod target_tunables;
|
mod target_tunables;
|
||||||
|
|
||||||
pub use crate::action::{ActionError, ActionOutcome, RuntimeValue};
|
pub use crate::action::{ActionError, ActionOutcome, RuntimeValue};
|
||||||
|
pub use crate::code_memory::CodeMemory;
|
||||||
pub use crate::compiler::{CompilationStrategy, Compiler};
|
pub use crate::compiler::{CompilationStrategy, Compiler};
|
||||||
pub use crate::context::{Context, ContextError, Features, UnknownInstance};
|
pub use crate::context::{Context, ContextError, Features, UnknownInstance};
|
||||||
pub use crate::instantiate::{instantiate, CompiledModule, SetupError};
|
pub use crate::instantiate::{instantiate, CompiledModule, SetupError};
|
||||||
|
|||||||
Reference in New Issue
Block a user