mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 06:38:22 +00:00
Merge branch 'master' into wasix-merge
This commit is contained in:
@@ -132,7 +132,11 @@ impl Imports {
|
||||
/// Resolve and return a vector of imports in the order they are defined in the `module`'s source code.
|
||||
///
|
||||
/// This means the returned `Vec<Extern>` might be a subset of the imports contained in `self`.
|
||||
pub fn imports_for_module(&self, module: &Module) -> Result<Vec<Extern>, LinkError> {
|
||||
pub fn imports_for_module(
|
||||
&self,
|
||||
module: &Module,
|
||||
_store: &mut impl AsStoreMut,
|
||||
) -> Result<Vec<Extern>, LinkError> {
|
||||
let mut ret = vec![];
|
||||
for import in module.imports() {
|
||||
if let Some(imp) = self
|
||||
|
||||
@@ -54,7 +54,7 @@ pub use crate::js::function_env::{FunctionEnv, FunctionEnvMut};
|
||||
pub use crate::js::imports::Imports;
|
||||
pub use crate::js::instance::Instance;
|
||||
pub use crate::js::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter};
|
||||
pub use crate::js::module::{Module, ModuleTypeHints};
|
||||
pub use crate::js::module::{IoCompileError, Module, ModuleTypeHints};
|
||||
pub use crate::js::native::TypedFunction;
|
||||
pub use crate::js::native_type::NativeWasmTypeInto;
|
||||
pub use crate::js::ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64};
|
||||
@@ -73,7 +73,6 @@ pub use crate::js::value::Value as Val;
|
||||
|
||||
pub mod vm {
|
||||
//! The `vm` module re-exports wasmer-vm types.
|
||||
|
||||
pub use crate::js::export::VMMemory;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ use wasmer_types::{
|
||||
Pages, TableType, Type,
|
||||
};
|
||||
|
||||
/// IO Error on a Module Compilation
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "std", derive(Error))]
|
||||
pub enum IoCompileError {
|
||||
|
||||
@@ -58,16 +58,26 @@ impl Imports {
|
||||
/// import_object.get_export("module", "name");
|
||||
/// ```
|
||||
pub fn get_export(&self, module: &str, name: &str) -> Option<Extern> {
|
||||
if self
|
||||
.map
|
||||
.contains_key(&(module.to_string(), name.to_string()))
|
||||
{
|
||||
if self.exists(module, name) {
|
||||
let ext = &self.map[&(module.to_string(), name.to_string())];
|
||||
return Some(ext.clone());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns if an export exist for a given module and name.
|
||||
///
|
||||
/// # Usage
|
||||
/// ```no_run
|
||||
/// # use wasmer::Imports;
|
||||
/// let mut import_object = Imports::new();
|
||||
/// import_object.exists("module", "name");
|
||||
/// ```
|
||||
pub fn exists(&self, module: &str, name: &str) -> bool {
|
||||
self.map
|
||||
.contains_key(&(module.to_string(), name.to_string()))
|
||||
}
|
||||
|
||||
/// Returns true if the Imports contains namespace with the provided name.
|
||||
pub fn contains_namespace(&self, name: &str) -> bool {
|
||||
self.map.keys().any(|(k, _)| (k == name))
|
||||
|
||||
@@ -23,7 +23,7 @@ pub use crate::sys::function_env::{FunctionEnv, FunctionEnvMut};
|
||||
pub use crate::sys::imports::Imports;
|
||||
pub use crate::sys::instance::{Instance, InstantiationError};
|
||||
pub use crate::sys::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter};
|
||||
pub use crate::sys::module::Module;
|
||||
pub use crate::sys::module::{IoCompileError, Module};
|
||||
pub use crate::sys::native::TypedFunction;
|
||||
pub use crate::sys::native_type::NativeWasmTypeInto;
|
||||
pub use crate::sys::store::{AsStoreMut, AsStoreRef, StoreMut, StoreRef};
|
||||
@@ -74,9 +74,9 @@ pub use wasmer_compiler_cranelift::{Cranelift, CraneliftOptLevel};
|
||||
#[cfg(feature = "llvm")]
|
||||
pub use wasmer_compiler_llvm::{LLVMOptLevel, LLVM};
|
||||
|
||||
pub use wasmer_compiler::Engine;
|
||||
#[cfg(feature = "compiler")]
|
||||
pub use wasmer_compiler::{Artifact, EngineBuilder};
|
||||
pub use wasmer_compiler::{AsEngineRef, Engine, EngineRef};
|
||||
|
||||
/// Version number of this crate.
|
||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
#[cfg(feature = "compiler")]
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_compiler::Artifact;
|
||||
use wasmer_compiler::ArtifactCreate;
|
||||
use wasmer_compiler::AsEngineRef;
|
||||
#[cfg(feature = "wat")]
|
||||
use wasmer_types::WasmError;
|
||||
use wasmer_types::{CompileError, ExportsIterator, ImportsIterator, ModuleInfo};
|
||||
use wasmer_types::{
|
||||
CompileError, DeserializeError, ExportsIterator, ImportsIterator, ModuleInfo, SerializeError,
|
||||
};
|
||||
use wasmer_types::{ExportType, ImportType};
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
@@ -16,6 +18,7 @@ use crate::{sys::InstantiationError, AsStoreMut, AsStoreRef, IntoBytes};
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_vm::InstanceHandle;
|
||||
|
||||
/// IO Error on a Module Compilation
|
||||
#[derive(Error, Debug)]
|
||||
pub enum IoCompileError {
|
||||
/// An IO error
|
||||
@@ -50,8 +53,7 @@ pub struct Module {
|
||||
//
|
||||
// In the future, this code should be refactored to properly describe the
|
||||
// ownership of the code and its metadata.
|
||||
#[cfg(feature = "compiler")]
|
||||
artifact: Arc<wasmer_compiler::Artifact>,
|
||||
artifact: Arc<Artifact>,
|
||||
module_info: Arc<ModuleInfo>,
|
||||
}
|
||||
|
||||
@@ -116,33 +118,38 @@ impl Module {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
/// # Example of loading a module using just an `Engine` and no `Store`
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::*;
|
||||
/// #
|
||||
/// # let compiler = Cranelift::default();
|
||||
/// # let engine = EngineBuilder::new(compiler).engine();
|
||||
///
|
||||
/// let module = Module::from_file(&engine, "path/to/foo.wasm");
|
||||
/// ```
|
||||
#[allow(unreachable_code)]
|
||||
pub fn new(store: &impl AsStoreRef, bytes: impl IntoBytes) -> Result<Self, CompileError> {
|
||||
#[allow(unused_mut)]
|
||||
let mut bytes = bytes.into_bytes();
|
||||
pub fn new(engine: &impl AsEngineRef, bytes: impl AsRef<[u8]>) -> Result<Self, CompileError> {
|
||||
#[cfg(feature = "wat")]
|
||||
if bytes.starts_with(b"\0asm") == false {
|
||||
let parsed_bytes = wat::parse_bytes(&bytes[..]).map_err(|e| {
|
||||
CompileError::Wasm(WasmError::Generic(format!(
|
||||
"Error when converting wat: {}",
|
||||
e
|
||||
)))
|
||||
})?;
|
||||
bytes = bytes::Bytes::from(parsed_bytes.to_vec());
|
||||
}
|
||||
Self::from_binary(store, bytes.as_ref())
|
||||
let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| {
|
||||
CompileError::Wasm(WasmError::Generic(format!(
|
||||
"Error when converting wat: {}",
|
||||
e
|
||||
)))
|
||||
})?;
|
||||
Self::from_binary(engine, bytes.as_ref())
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
/// Creates a new WebAssembly module from a file path.
|
||||
pub fn from_file(
|
||||
store: &impl AsStoreRef,
|
||||
engine: &impl AsEngineRef,
|
||||
file: impl AsRef<Path>,
|
||||
) -> Result<Self, IoCompileError> {
|
||||
let file_ref = file.as_ref();
|
||||
let canonical = file_ref.canonicalize()?;
|
||||
let wasm_bytes = std::fs::read(file_ref)?;
|
||||
let mut module = Self::new(store, &wasm_bytes)?;
|
||||
let mut module = Self::new(engine, &wasm_bytes)?;
|
||||
// Set the module name to the absolute path of the filename.
|
||||
// This is useful for debugging the stack traces.
|
||||
let filename = canonical.as_path().to_str().unwrap();
|
||||
@@ -156,9 +163,9 @@ impl Module {
|
||||
/// Opposed to [`Module::new`], this function is not compatible with
|
||||
/// the WebAssembly text format (if the "wat" feature is enabled for
|
||||
/// this crate).
|
||||
pub fn from_binary(store: &impl AsStoreRef, binary: &[u8]) -> Result<Self, CompileError> {
|
||||
Self::validate(store, binary)?;
|
||||
unsafe { Self::from_binary_unchecked(store, binary) }
|
||||
pub fn from_binary(engine: &impl AsEngineRef, binary: &[u8]) -> Result<Self, CompileError> {
|
||||
Self::validate(engine, binary)?;
|
||||
unsafe { Self::from_binary_unchecked(engine, binary) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
@@ -170,11 +177,10 @@ impl Module {
|
||||
/// in environments where the WebAssembly modules are trusted and validated
|
||||
/// beforehand.
|
||||
pub unsafe fn from_binary_unchecked(
|
||||
store: &impl AsStoreRef,
|
||||
binary: impl IntoBytes,
|
||||
engine: &impl AsEngineRef,
|
||||
binary: &[u8],
|
||||
) -> Result<Self, CompileError> {
|
||||
let binary = binary.into_bytes();
|
||||
let module = Self::compile(store, binary)?;
|
||||
let module = Self::compile(engine, binary)?;
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
@@ -185,24 +191,18 @@ impl Module {
|
||||
/// This validation is normally pretty fast and checks the enabled
|
||||
/// WebAssembly features in the Store Engine to assure deterministic
|
||||
/// validation of the Module.
|
||||
pub fn validate(store: &impl AsStoreRef, binary: impl IntoBytes) -> Result<(), CompileError> {
|
||||
let binary = binary.into_bytes();
|
||||
store.as_store_ref().engine().validate(&binary[..])
|
||||
pub fn validate(engine: &impl AsEngineRef, binary: &[u8]) -> Result<(), CompileError> {
|
||||
engine.as_engine_ref().engine().validate(binary)
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
fn compile(store: &impl AsStoreRef, binary: impl IntoBytes) -> Result<Self, CompileError> {
|
||||
let binary = binary.into_bytes();
|
||||
let artifact = store
|
||||
.as_store_ref()
|
||||
.engine()
|
||||
.compile(&binary[..], store.as_store_ref().tunables())?;
|
||||
fn compile(engine: &impl AsEngineRef, binary: &[u8]) -> Result<Self, CompileError> {
|
||||
let artifact = engine.as_engine_ref().engine().compile(binary)?;
|
||||
Ok(Self::from_artifact(artifact))
|
||||
}
|
||||
|
||||
/// Serializes a module into a binary representation that the `Engine`
|
||||
/// can later process via
|
||||
#[cfg(feature = "enable-rkyv")]
|
||||
#[cfg_attr(feature = "compiler", doc = "[`Module::deserialize`].")]
|
||||
#[cfg_attr(not(feature = "compiler"), doc = "`Module::deserialize`.")]
|
||||
///
|
||||
@@ -217,13 +217,12 @@ impl Module {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn serialize(&self) -> Result<bytes::Bytes, wasmer_types::SerializeError> {
|
||||
pub fn serialize(&self) -> Result<Bytes, SerializeError> {
|
||||
self.artifact.serialize().map(|bytes| bytes.into())
|
||||
}
|
||||
|
||||
/// Serializes a module into a file that the `Engine`
|
||||
/// can later process via
|
||||
#[cfg(feature = "enable-rkyv")]
|
||||
#[cfg_attr(feature = "compiler", doc = "[`Module::deserialize_from_file`].")]
|
||||
#[cfg_attr(not(feature = "compiler"), doc = "`Module::deserialize_from_file`.")]
|
||||
///
|
||||
@@ -238,14 +237,10 @@ impl Module {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn serialize_to_file(
|
||||
&self,
|
||||
path: impl AsRef<Path>,
|
||||
) -> Result<(), wasmer_types::SerializeError> {
|
||||
pub fn serialize_to_file(&self, path: impl AsRef<Path>) -> Result<(), SerializeError> {
|
||||
self.artifact.serialize_to_file(path.as_ref())
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable-rkyv")]
|
||||
#[cfg(feature = "compiler")]
|
||||
/// Deserializes a serialized Module binary into a `Module`.
|
||||
/// > Note: the module has to be serialized before with the `serialize` method.
|
||||
@@ -273,13 +268,12 @@ impl Module {
|
||||
pub unsafe fn deserialize(
|
||||
store: &impl AsStoreRef,
|
||||
bytes: impl IntoBytes,
|
||||
) -> Result<Self, wasmer_types::DeserializeError> {
|
||||
let bytes = bytes.into_bytes().to_vec();
|
||||
) -> Result<Self, DeserializeError> {
|
||||
let bytes = bytes.into_bytes();
|
||||
let artifact = store.as_store_ref().engine().deserialize(&bytes)?;
|
||||
Ok(Self::from_artifact(artifact))
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable-rkyv")]
|
||||
#[cfg(feature = "compiler")]
|
||||
/// Deserializes a a serialized Module located in a `Path` into a `Module`.
|
||||
/// > Note: the module has to be serialized before with the `serialize` method.
|
||||
@@ -301,7 +295,7 @@ impl Module {
|
||||
pub unsafe fn deserialize_from_file(
|
||||
store: &impl AsStoreRef,
|
||||
path: impl AsRef<Path>,
|
||||
) -> Result<Self, wasmer_types::DeserializeError> {
|
||||
) -> Result<Self, DeserializeError> {
|
||||
let artifact = store
|
||||
.as_store_ref()
|
||||
.engine()
|
||||
@@ -309,8 +303,7 @@ impl Module {
|
||||
Ok(Self::from_artifact(artifact))
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
fn from_artifact(artifact: Arc<wasmer_compiler::Artifact>) -> Self {
|
||||
fn from_artifact(artifact: Arc<Artifact>) -> Self {
|
||||
Self {
|
||||
module_info: Arc::new(artifact.create_module_info()),
|
||||
artifact,
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
#[cfg(feature = "compiler")]
|
||||
use crate::sys::tunables::BaseTunables;
|
||||
use derivative::Derivative;
|
||||
use std::fmt;
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_compiler::{Engine, EngineBuilder, Tunables};
|
||||
use wasmer_compiler::{AsEngineRef, Engine, EngineBuilder, EngineRef, Tunables};
|
||||
use wasmer_vm::{init_traps, StoreId, TrapHandler, TrapHandlerFn};
|
||||
use wasmer_types::{OnCalledAction, StoreSnapshot};
|
||||
#[cfg(feature = "compiler")]
|
||||
use wasmer_vm::init_traps;
|
||||
use wasmer_vm::{StoreId, TrapHandler, TrapHandlerFn};
|
||||
|
||||
use wasmer_vm::StoreObjects;
|
||||
|
||||
@@ -22,9 +19,6 @@ pub(crate) struct StoreInner {
|
||||
#[cfg(feature = "compiler")]
|
||||
pub(crate) engine: Engine,
|
||||
#[derivative(Debug = "ignore")]
|
||||
#[cfg(feature = "compiler")]
|
||||
pub(crate) tunables: Box<dyn Tunables + Send + Sync>,
|
||||
#[derivative(Debug = "ignore")]
|
||||
pub(crate) trap_handler: Option<Box<TrapHandlerFn<'static>>>,
|
||||
#[derivative(Debug = "ignore")]
|
||||
pub(crate) on_called: Option<
|
||||
@@ -55,10 +49,7 @@ impl StoreInner {
|
||||
/// have been allocated during the lifetime of the abstract machine.
|
||||
///
|
||||
/// The `Store` holds the engine (that is —amongst many things— used to compile
|
||||
/// the Wasm bytes into a valid module artifact), in addition to the
|
||||
#[cfg_attr(feature = "compiler", doc = "[`Tunables`]")]
|
||||
#[cfg_attr(not(feature = "compiler"), doc = "`Tunables`")]
|
||||
/// (that are used to create the memories, tables and globals).
|
||||
/// the Wasm bytes into a valid module artifact).
|
||||
///
|
||||
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#store>
|
||||
pub struct Store {
|
||||
@@ -72,8 +63,21 @@ impl Store {
|
||||
/// Creates a new `Store` with a specific [`Engine`].
|
||||
pub fn new(engine: impl Into<Engine>) -> Self {
|
||||
let engine = engine.into();
|
||||
let target = engine.target().clone();
|
||||
Self::new_with_tunables(engine, BaseTunables::for_target(&target))
|
||||
|
||||
// Make sure the signal handlers are installed.
|
||||
// This is required for handling traps.
|
||||
init_traps();
|
||||
|
||||
Self {
|
||||
inner: Box::new(StoreInner {
|
||||
objects: Default::default(),
|
||||
engine: engine.cloned(),
|
||||
trap_handler: None,
|
||||
on_called: None,
|
||||
}),
|
||||
engine: engine.cloned(),
|
||||
trap_handler: Arc::new(RwLock::new(None)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
@@ -97,28 +101,16 @@ impl Store {
|
||||
engine: impl Into<Engine>,
|
||||
tunables: impl Tunables + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
let engine = engine.into();
|
||||
let mut engine = engine.into();
|
||||
engine.set_tunables(tunables);
|
||||
|
||||
// Make sure the signal handlers are installed.
|
||||
// This is required for handling traps.
|
||||
init_traps();
|
||||
|
||||
Self {
|
||||
inner: Box::new(StoreInner {
|
||||
objects: Default::default(),
|
||||
engine: engine.cloned(),
|
||||
tunables: Box::new(tunables),
|
||||
trap_handler: None,
|
||||
on_called: None,
|
||||
}),
|
||||
engine: engine.cloned(),
|
||||
}
|
||||
Self::new(engine)
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
/// Returns the [`Tunables`].
|
||||
pub fn tunables(&self) -> &dyn Tunables {
|
||||
self.inner.tunables.as_ref()
|
||||
self.engine.tunables()
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
@@ -236,6 +228,34 @@ impl AsStoreMut for Store {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
impl AsEngineRef for Store {
|
||||
fn as_engine_ref(&self) -> EngineRef<'_> {
|
||||
EngineRef::new(&self.engine)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
impl AsEngineRef for &Store {
|
||||
fn as_engine_ref(&self) -> EngineRef<'_> {
|
||||
EngineRef::new(&self.engine)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
impl AsEngineRef for StoreRef<'_> {
|
||||
fn as_engine_ref(&self) -> EngineRef<'_> {
|
||||
EngineRef::new(&self.inner.engine)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
impl AsEngineRef for StoreMut<'_> {
|
||||
fn as_engine_ref(&self) -> EngineRef<'_> {
|
||||
EngineRef::new(&self.inner.engine)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Store {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Store").finish()
|
||||
@@ -255,7 +275,7 @@ impl<'a> StoreRef<'a> {
|
||||
#[cfg(feature = "compiler")]
|
||||
/// Returns the [`Tunables`].
|
||||
pub fn tunables(&self) -> &dyn Tunables {
|
||||
self.inner.tunables.as_ref()
|
||||
self.inner.engine.tunables()
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
@@ -296,7 +316,7 @@ impl<'a> StoreMut<'a> {
|
||||
/// Returns the [`Tunables`].
|
||||
#[cfg(feature = "compiler")]
|
||||
pub fn tunables(&self) -> &dyn Tunables {
|
||||
self.inner.tunables.as_ref()
|
||||
self.inner.engine.tunables()
|
||||
}
|
||||
|
||||
/// Returns the [`Engine`].
|
||||
@@ -325,10 +345,9 @@ impl<'a> StoreMut<'a> {
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
pub(crate) fn tunables_and_objects_mut(&mut self) -> (&dyn Tunables, &mut StoreObjects) {
|
||||
(self.inner.tunables.as_ref(), &mut self.inner.objects)
|
||||
(self.inner.engine.tunables(), &mut self.inner.objects)
|
||||
}
|
||||
|
||||
#[cfg(feature = "compiler")]
|
||||
pub(crate) fn as_raw(&self) -> *mut StoreInner {
|
||||
self.inner as *const StoreInner as *mut StoreInner
|
||||
}
|
||||
|
||||
@@ -1,140 +1,20 @@
|
||||
use crate::sys::{MemoryType, Pages, TableType};
|
||||
use std::ptr::NonNull;
|
||||
use wasmer_compiler::Tunables;
|
||||
use wasmer_types::{PointerWidth, Target};
|
||||
use wasmer_vm::MemoryError;
|
||||
use wasmer_vm::{
|
||||
MemoryStyle, TableStyle, VMMemory, VMMemoryDefinition, VMTable, VMTableDefinition,
|
||||
};
|
||||
pub use wasmer_compiler::BaseTunables;
|
||||
|
||||
/// Tunable parameters for WebAssembly compilation.
|
||||
/// This is the reference implementation of the `Tunables` trait,
|
||||
/// used by default.
|
||||
///
|
||||
/// You can use this as a template for creating a custom Tunables
|
||||
/// implementation or use composition to wrap your Tunables around
|
||||
/// this one. The later approach is demonstrated in the
|
||||
/// tunables-limit-memory example.
|
||||
#[derive(Clone)]
|
||||
pub struct BaseTunables {
|
||||
/// For static heaps, the size in wasm pages of the heap protected by bounds checking.
|
||||
pub static_memory_bound: Pages,
|
||||
|
||||
/// The size in bytes of the offset guard for static heaps.
|
||||
pub static_memory_offset_guard_size: u64,
|
||||
|
||||
/// The size in bytes of the offset guard for dynamic heaps.
|
||||
pub dynamic_memory_offset_guard_size: u64,
|
||||
}
|
||||
|
||||
impl BaseTunables {
|
||||
/// Get the `BaseTunables` for a specific Target
|
||||
pub fn for_target(target: &Target) -> Self {
|
||||
let triple = target.triple();
|
||||
let pointer_width: PointerWidth = triple.pointer_width().unwrap();
|
||||
let (static_memory_bound, static_memory_offset_guard_size): (Pages, u64) =
|
||||
match pointer_width {
|
||||
PointerWidth::U16 => (0x400.into(), 0x1000),
|
||||
PointerWidth::U32 => (0x4000.into(), 0x1_0000),
|
||||
// Static Memory Bound:
|
||||
// Allocating 4 GiB of address space let us avoid the
|
||||
// need for explicit bounds checks.
|
||||
// Static Memory Guard size:
|
||||
// Allocating 2 GiB of address space lets us translate wasm
|
||||
// offsets into x86 offsets as aggressively as we can.
|
||||
PointerWidth::U64 => (0x1_0000.into(), 0x8000_0000),
|
||||
};
|
||||
|
||||
// Allocate a small guard to optimize common cases but without
|
||||
// wasting too much memory.
|
||||
// The Windows memory manager seems more laxed than the other ones
|
||||
// And a guard of just 1 page may not be enough is some borderline cases
|
||||
// So using 2 pages for guard on this platform
|
||||
#[cfg(target_os = "windows")]
|
||||
let dynamic_memory_offset_guard_size: u64 = 0x2_0000;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let dynamic_memory_offset_guard_size: u64 = 0x1_0000;
|
||||
|
||||
Self {
|
||||
static_memory_bound,
|
||||
static_memory_offset_guard_size,
|
||||
dynamic_memory_offset_guard_size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tunables for BaseTunables {
|
||||
/// Get a `MemoryStyle` for the provided `MemoryType`
|
||||
fn memory_style(&self, memory: &MemoryType) -> MemoryStyle {
|
||||
// A heap with a maximum that doesn't exceed the static memory bound specified by the
|
||||
// tunables make it static.
|
||||
//
|
||||
// If the module doesn't declare an explicit maximum treat it as 4GiB.
|
||||
let maximum = memory.maximum.unwrap_or_else(Pages::max_value);
|
||||
if maximum <= self.static_memory_bound {
|
||||
MemoryStyle::Static {
|
||||
// Bound can be larger than the maximum for performance reasons
|
||||
bound: self.static_memory_bound,
|
||||
offset_guard_size: self.static_memory_offset_guard_size,
|
||||
}
|
||||
} else {
|
||||
MemoryStyle::Dynamic {
|
||||
offset_guard_size: self.dynamic_memory_offset_guard_size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a [`TableStyle`] for the provided [`TableType`].
|
||||
fn table_style(&self, _table: &TableType) -> TableStyle {
|
||||
TableStyle::CallerChecksSignature
|
||||
}
|
||||
|
||||
/// Create a memory owned by the host given a [`MemoryType`] and a [`MemoryStyle`].
|
||||
fn create_host_memory(
|
||||
&self,
|
||||
ty: &MemoryType,
|
||||
style: &MemoryStyle,
|
||||
) -> Result<VMMemory, MemoryError> {
|
||||
VMMemory::new(ty, style)
|
||||
}
|
||||
|
||||
/// Create a memory owned by the VM given a [`MemoryType`] and a [`MemoryStyle`].
|
||||
///
|
||||
/// # Safety
|
||||
/// - `vm_definition_location` must point to a valid, owned `VMMemoryDefinition`,
|
||||
/// for example in `VMContext`.
|
||||
unsafe fn create_vm_memory(
|
||||
&self,
|
||||
ty: &MemoryType,
|
||||
style: &MemoryStyle,
|
||||
vm_definition_location: NonNull<VMMemoryDefinition>,
|
||||
) -> Result<VMMemory, MemoryError> {
|
||||
VMMemory::from_definition(ty, style, vm_definition_location)
|
||||
}
|
||||
|
||||
/// Create a table owned by the host given a [`TableType`] and a [`TableStyle`].
|
||||
fn create_host_table(&self, ty: &TableType, style: &TableStyle) -> Result<VMTable, String> {
|
||||
VMTable::new(ty, style)
|
||||
}
|
||||
|
||||
/// Create a table owned by the VM given a [`TableType`] and a [`TableStyle`].
|
||||
///
|
||||
/// # Safety
|
||||
/// - `vm_definition_location` must point to a valid, owned `VMTableDefinition`,
|
||||
/// for example in `VMContext`.
|
||||
unsafe fn create_vm_table(
|
||||
&self,
|
||||
ty: &TableType,
|
||||
style: &TableStyle,
|
||||
vm_definition_location: NonNull<VMTableDefinition>,
|
||||
) -> Result<VMTable, String> {
|
||||
VMTable::from_definition(ty, style, vm_definition_location)
|
||||
}
|
||||
}
|
||||
// All BaseTunable definition now is in wasmer_compile crate
|
||||
// Tests are still here
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::sys::TableType;
|
||||
use std::cell::UnsafeCell;
|
||||
use std::ptr::NonNull;
|
||||
use wasmer_compiler::Tunables;
|
||||
use wasmer_types::{MemoryType, Pages, WASM_PAGE_SIZE};
|
||||
use wasmer_vm::{
|
||||
LinearMemory, MemoryError, MemoryStyle, TableStyle, VMMemory, VMMemoryDefinition, VMTable,
|
||||
VMTableDefinition,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn memory_style() {
|
||||
@@ -175,11 +55,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::ptr::NonNull;
|
||||
use wasmer_types::{MemoryError, MemoryStyle, MemoryType, Pages, WASM_PAGE_SIZE};
|
||||
use wasmer_vm::LinearMemory;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VMTinyMemory {
|
||||
mem: Vec<u8>,
|
||||
|
||||
Reference in New Issue
Block a user