mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-13 00:51:20 +00:00
Change memory api
This commit is contained in:
@ -3,7 +3,7 @@ use crate::{
|
||||
export::{Context, Export},
|
||||
global::Global,
|
||||
import::ImportObject,
|
||||
memory::Memory,
|
||||
memory::{Memory, MemoryVariant},
|
||||
module::{ImportName, ModuleInner},
|
||||
structures::{BoxedMap, Map, SliceMap, TypedIndex},
|
||||
table::Table,
|
||||
@ -17,7 +17,7 @@ use std::slice;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LocalBacking {
|
||||
pub(crate) memories: BoxedMap<LocalMemoryIndex, Memory>,
|
||||
pub(crate) memories: BoxedMap<LocalMemoryIndex, MemoryVariant>,
|
||||
pub(crate) tables: BoxedMap<LocalTableIndex, Table>,
|
||||
pub(crate) globals: BoxedMap<LocalGlobalIndex, Global>,
|
||||
|
||||
@ -57,7 +57,7 @@ impl LocalBacking {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_memories(module: &ModuleInner) -> BoxedMap<LocalMemoryIndex, Memory> {
|
||||
fn generate_memories(module: &ModuleInner) -> BoxedMap<LocalMemoryIndex, MemoryVariant> {
|
||||
let mut memories = Map::with_capacity(module.memories.len());
|
||||
|
||||
for (_, &desc) in &module.memories {
|
||||
@ -70,8 +70,13 @@ impl LocalBacking {
|
||||
// } else {
|
||||
// Memory::new(memory.minimum, memory.maximum.map(|m| m as u32))
|
||||
// };
|
||||
let memory = Memory::new(desc).expect("unable to create memory");
|
||||
memories.push(memory);
|
||||
let memory_variant = if desc.shared {
|
||||
MemoryVariant::Shared(Memory::new(desc).expect("unable to create memory"))
|
||||
} else {
|
||||
MemoryVariant::Unshared(Memory::new(desc).expect("unable to create memory"))
|
||||
};
|
||||
|
||||
memories.push(memory_variant);
|
||||
}
|
||||
|
||||
memories.into_boxed_map()
|
||||
@ -80,7 +85,7 @@ impl LocalBacking {
|
||||
fn finalize_memories(
|
||||
module: &ModuleInner,
|
||||
imports: &ImportBacking,
|
||||
memories: &mut SliceMap<LocalMemoryIndex, Memory>,
|
||||
memories: &mut SliceMap<LocalMemoryIndex, MemoryVariant>,
|
||||
) -> BoxedMap<LocalMemoryIndex, *mut vm::LocalMemory> {
|
||||
// For each init that has some data...
|
||||
for init in module
|
||||
@ -107,7 +112,14 @@ impl LocalBacking {
|
||||
assert!(memory_desc.minimum.bytes().0 >= data_top);
|
||||
|
||||
let mem = &memories[local_memory_index];
|
||||
mem.write_many(init_base as u32, &init.data).unwrap();
|
||||
match mem {
|
||||
MemoryVariant::Unshared(unshared_mem) => unshared_mem.access_mut()
|
||||
[init_base..init_base + init.data.len()]
|
||||
.copy_from_slice(&init.data),
|
||||
MemoryVariant::Shared(shared_mem) => shared_mem.access_mut()
|
||||
[init_base..init_base + init.data.len()]
|
||||
.copy_from_slice(&init.data),
|
||||
}
|
||||
}
|
||||
LocalOrImport::Import(imported_memory_index) => {
|
||||
// Write the initialization data to the memory that
|
||||
@ -127,7 +139,10 @@ impl LocalBacking {
|
||||
|
||||
memories
|
||||
.iter_mut()
|
||||
.map(|(_, mem)| mem.vm_local_memory())
|
||||
.map(|(_, mem)| match mem {
|
||||
MemoryVariant::Unshared(unshared_mem) => unshared_mem.vm_local_memory(),
|
||||
MemoryVariant::Shared(shared_mem) => shared_mem.vm_local_memory(),
|
||||
})
|
||||
.collect::<Map<_, _>>()
|
||||
.into_boxed_map()
|
||||
}
|
||||
@ -283,7 +298,7 @@ impl LocalBacking {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImportBacking {
|
||||
pub(crate) memories: BoxedMap<ImportedMemoryIndex, Memory>,
|
||||
pub(crate) memories: BoxedMap<ImportedMemoryIndex, MemoryVariant>,
|
||||
pub(crate) tables: BoxedMap<ImportedTableIndex, Table>,
|
||||
pub(crate) globals: BoxedMap<ImportedGlobalIndex, Global>,
|
||||
|
||||
@ -418,7 +433,7 @@ fn import_memories(
|
||||
module: &ModuleInner,
|
||||
imports: &ImportObject,
|
||||
) -> LinkResult<(
|
||||
BoxedMap<ImportedMemoryIndex, Memory>,
|
||||
BoxedMap<ImportedMemoryIndex, MemoryVariant>,
|
||||
BoxedMap<ImportedMemoryIndex, *mut vm::LocalMemory>,
|
||||
)> {
|
||||
let mut link_errors = vec![];
|
||||
@ -432,15 +447,22 @@ fn import_memories(
|
||||
.and_then(|namespace| namespace.get_export(&name));
|
||||
match memory_import {
|
||||
Some(Export::Memory(mut memory)) => {
|
||||
if expected_memory_desc.fits_in_imported(memory.descriptor()) {
|
||||
let (descriptor, vm_local_memory) = match &mut memory {
|
||||
MemoryVariant::Unshared(unshared_mem) => {
|
||||
(unshared_mem.descriptor(), unshared_mem.vm_local_memory())
|
||||
}
|
||||
MemoryVariant::Shared(_) => unimplemented!(),
|
||||
};
|
||||
|
||||
if expected_memory_desc.fits_in_imported(descriptor) {
|
||||
memories.push(memory.clone());
|
||||
vm_memories.push(memory.vm_local_memory());
|
||||
vm_memories.push(vm_local_memory);
|
||||
} else {
|
||||
link_errors.push(LinkError::IncorrectMemoryDescriptor {
|
||||
namespace: namespace.clone(),
|
||||
name: name.clone(),
|
||||
expected: *expected_memory_desc,
|
||||
found: memory.descriptor(),
|
||||
found: descriptor,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,6 @@ impl From<ResolveError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<CallError> for Error {
|
||||
fn from(call_err: CallError) -> Self {
|
||||
Error::CallError(call_err)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
global::Global, instance::InstanceInner, memory::Memory, module::ExportIndex,
|
||||
global::Global, instance::InstanceInner, memory::MemoryVariant, module::ExportIndex,
|
||||
module::ModuleInner, table::Table, types::FuncSig, vm,
|
||||
};
|
||||
use hashbrown::hash_map;
|
||||
@ -18,7 +18,7 @@ pub enum Export {
|
||||
ctx: Context,
|
||||
signature: Arc<FuncSig>,
|
||||
},
|
||||
Memory(Memory),
|
||||
Memory(MemoryVariant),
|
||||
Table(Table),
|
||||
Global(Global),
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
export::{Context, Export, ExportIter, FuncPointer},
|
||||
global::Global,
|
||||
import::{ImportObject, LikeNamespace},
|
||||
memory::Memory,
|
||||
memory::MemoryVariant,
|
||||
module::{ExportIndex, Module, ModuleInner},
|
||||
table::Table,
|
||||
typed_func::{Func, Safe, WasmTypeList},
|
||||
@ -372,7 +372,7 @@ impl InstanceInner {
|
||||
(unsafe { FuncPointer::new(func_ptr) }, ctx, signature)
|
||||
}
|
||||
|
||||
fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> Memory {
|
||||
fn get_memory_from_index(&self, module: &ModuleInner, mem_index: MemoryIndex) -> MemoryVariant {
|
||||
match mem_index.local_or_import(module) {
|
||||
LocalOrImport::Local(local_mem_index) => self.backing.memories[local_mem_index].clone(),
|
||||
LocalOrImport::Import(imported_mem_index) => {
|
||||
|
@ -4,11 +4,18 @@ use crate::{
|
||||
import::IsExport,
|
||||
memory::dynamic::DYNAMIC_GUARD_SIZE,
|
||||
memory::static_::{SAFE_STATIC_GUARD_SIZE, SAFE_STATIC_HEAP_SIZE},
|
||||
types::{MemoryDescriptor, ValueType},
|
||||
types::MemoryDescriptor,
|
||||
units::Pages,
|
||||
vm,
|
||||
};
|
||||
use std::{cell::RefCell, fmt, mem, ptr, rc::Rc, slice};
|
||||
use std::{
|
||||
cell::{Cell, Ref, RefCell, RefMut},
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
ptr,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
pub use self::dynamic::DynamicMemory;
|
||||
pub use self::static_::{SharedStaticMemory, StaticMemory};
|
||||
@ -16,12 +23,68 @@ pub use self::static_::{SharedStaticMemory, StaticMemory};
|
||||
mod dynamic;
|
||||
mod static_;
|
||||
|
||||
pub struct Memory {
|
||||
desc: MemoryDescriptor,
|
||||
storage: Rc<RefCell<(MemoryStorage, Box<vm::LocalMemory>)>>,
|
||||
pub trait MemoryImpl<'a>: Clone {
|
||||
type Access: Deref<Target = [u8]>;
|
||||
type AccessMut: DerefMut<Target = [u8]>;
|
||||
|
||||
fn new(desc: MemoryDescriptor) -> Result<Self, CreationError>;
|
||||
fn grow(&'a self, delta: Pages) -> Option<Pages>;
|
||||
fn size(&'a self) -> Pages;
|
||||
fn vm_local_memory(&'a self) -> *mut vm::LocalMemory;
|
||||
fn access(&'a self) -> Self::Access;
|
||||
fn access_mut(&'a self) -> Self::AccessMut;
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
pub trait SharedPolicy
|
||||
where
|
||||
Self: Sized,
|
||||
for<'a> Self::Memory: MemoryImpl<'a>,
|
||||
{
|
||||
const SHARED: bool;
|
||||
type Memory;
|
||||
fn transform_variant(variants: &MemoryVariant) -> &Memory<Self>;
|
||||
}
|
||||
pub struct Shared;
|
||||
impl SharedPolicy for Shared {
|
||||
const SHARED: bool = true;
|
||||
type Memory = SharedMemory;
|
||||
fn transform_variant(variants: &MemoryVariant) -> &Memory<Self> {
|
||||
match variants {
|
||||
MemoryVariant::Shared(shared_mem) => shared_mem,
|
||||
MemoryVariant::Unshared(_) => {
|
||||
panic!("cannot transform unshared memory to shared memory")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct Unshared;
|
||||
impl SharedPolicy for Unshared {
|
||||
const SHARED: bool = false;
|
||||
type Memory = UnsharedMemory;
|
||||
fn transform_variant(variants: &MemoryVariant) -> &Memory<Self> {
|
||||
match variants {
|
||||
MemoryVariant::Unshared(unshared_mem) => unshared_mem,
|
||||
MemoryVariant::Shared(_) => panic!("cannot transform shared memory to unshared memory"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for Memory<Shared> {}
|
||||
unsafe impl Sync for Memory<Shared> {}
|
||||
|
||||
pub struct Memory<S = Unshared>
|
||||
where
|
||||
S: SharedPolicy,
|
||||
{
|
||||
desc: MemoryDescriptor,
|
||||
memory: S::Memory,
|
||||
_phantom: PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S> Memory<S>
|
||||
where
|
||||
S: SharedPolicy,
|
||||
{
|
||||
/// Create a new `Memory` from a [`MemoryDescriptor`]
|
||||
///
|
||||
/// [`MemoryDescriptor`]: struct.MemoryDescriptor.html
|
||||
@ -40,30 +103,21 @@ impl Memory {
|
||||
/// shared: false,
|
||||
/// };
|
||||
///
|
||||
/// let memory = Memory::new(descriptor)?;
|
||||
/// let memory: Memory = Memory::new(descriptor)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn new(desc: MemoryDescriptor) -> Result<Self, CreationError> {
|
||||
let mut vm_local_memory = Box::new(vm::LocalMemory {
|
||||
base: ptr::null_mut(),
|
||||
bound: 0,
|
||||
memory: ptr::null_mut(),
|
||||
});
|
||||
|
||||
let memory_storage = match desc.memory_type() {
|
||||
MemoryType::Dynamic => {
|
||||
MemoryStorage::Dynamic(DynamicMemory::new(desc, &mut vm_local_memory)?)
|
||||
}
|
||||
MemoryType::Static => {
|
||||
MemoryStorage::Static(StaticMemory::new(desc, &mut vm_local_memory)?)
|
||||
}
|
||||
MemoryType::SharedStatic => unimplemented!("shared memories are not yet implemented"),
|
||||
};
|
||||
pub fn new(desc: MemoryDescriptor) -> Result<Memory<S>, CreationError> {
|
||||
assert_eq!(
|
||||
desc.shared,
|
||||
S::SHARED,
|
||||
"type parameter must match description"
|
||||
);
|
||||
|
||||
Ok(Memory {
|
||||
desc,
|
||||
storage: Rc::new(RefCell::new((memory_storage, vm_local_memory))),
|
||||
memory: S::Memory::new(desc)?,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
@ -76,192 +130,48 @@ impl Memory {
|
||||
}
|
||||
|
||||
/// Grow this memory by the specfied number of pages.
|
||||
pub fn grow(&mut self, delta: Pages) -> Option<Pages> {
|
||||
match &mut *self.storage.borrow_mut() {
|
||||
(MemoryStorage::Dynamic(ref mut dynamic_memory), ref mut local) => {
|
||||
dynamic_memory.grow(delta, local)
|
||||
}
|
||||
(MemoryStorage::Static(ref mut static_memory), ref mut local) => {
|
||||
static_memory.grow(delta, local)
|
||||
}
|
||||
(MemoryStorage::SharedStatic(_), _) => unimplemented!(),
|
||||
}
|
||||
pub fn grow(&self, delta: Pages) -> Option<Pages> {
|
||||
self.memory.grow(delta)
|
||||
}
|
||||
|
||||
/// The size, in wasm pages, of this memory.
|
||||
pub fn size(&self) -> Pages {
|
||||
match &*self.storage.borrow() {
|
||||
(MemoryStorage::Dynamic(ref dynamic_memory), _) => dynamic_memory.size(),
|
||||
(MemoryStorage::Static(ref static_memory), _) => static_memory.size(),
|
||||
(MemoryStorage::SharedStatic(_), _) => unimplemented!(),
|
||||
}
|
||||
self.memory.size()
|
||||
}
|
||||
|
||||
pub fn read<T: ValueType>(&self, offset: u32) -> Result<T, ()> {
|
||||
let offset = offset as usize;
|
||||
let borrow_ref = self.storage.borrow();
|
||||
let memory_storage = &borrow_ref.0;
|
||||
|
||||
let mem_slice = match memory_storage {
|
||||
MemoryStorage::Dynamic(ref dynamic_memory) => dynamic_memory.as_slice(),
|
||||
MemoryStorage::Static(ref static_memory) => static_memory.as_slice(),
|
||||
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||
};
|
||||
|
||||
if offset + mem::size_of::<T>() <= mem_slice.len() {
|
||||
T::from_le(&mem_slice[offset..]).map_err(|_| ())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
pub fn access(&self) -> <S::Memory as MemoryImpl>::Access {
|
||||
self.memory.access()
|
||||
}
|
||||
|
||||
pub fn write<T: ValueType>(&self, offset: u32, value: T) -> Result<(), ()> {
|
||||
let offset = offset as usize;
|
||||
let mut borrow_ref = self.storage.borrow_mut();
|
||||
let memory_storage = &mut borrow_ref.0;
|
||||
|
||||
let mem_slice = match memory_storage {
|
||||
MemoryStorage::Dynamic(ref mut dynamic_memory) => dynamic_memory.as_slice_mut(),
|
||||
MemoryStorage::Static(ref mut static_memory) => static_memory.as_slice_mut(),
|
||||
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||
};
|
||||
|
||||
if offset + mem::size_of::<T>() <= mem_slice.len() {
|
||||
value.into_le(&mut mem_slice[offset..]);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
pub fn access_mut(&self) -> <S::Memory as MemoryImpl>::AccessMut {
|
||||
self.memory.access_mut()
|
||||
}
|
||||
|
||||
pub fn read_many<T: ValueType>(&self, offset: u32, count: usize) -> Result<Vec<T>, ()> {
|
||||
let offset = offset as usize;
|
||||
let borrow_ref = self.storage.borrow();
|
||||
let memory_storage = &borrow_ref.0;
|
||||
|
||||
let mem_slice = match memory_storage {
|
||||
MemoryStorage::Dynamic(ref dynamic_memory) => dynamic_memory.as_slice(),
|
||||
MemoryStorage::Static(ref static_memory) => static_memory.as_slice(),
|
||||
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||
};
|
||||
|
||||
let bytes_size = count * mem::size_of::<T>();
|
||||
|
||||
if offset + bytes_size <= mem_slice.len() {
|
||||
let buffer = &mem_slice[offset..offset + bytes_size];
|
||||
let value_type_buffer = unsafe {
|
||||
slice::from_raw_parts(
|
||||
buffer.as_ptr() as *const T,
|
||||
buffer.len() / mem::size_of::<T>(),
|
||||
)
|
||||
};
|
||||
Ok(value_type_buffer.to_vec())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_many<T: ValueType>(&self, offset: u32, values: &[T]) -> Result<(), ()> {
|
||||
let offset = offset as usize;
|
||||
let mut borrow_ref = self.storage.borrow_mut();
|
||||
let memory_storage = &mut borrow_ref.0;
|
||||
|
||||
let mem_slice = match memory_storage {
|
||||
MemoryStorage::Dynamic(ref mut dynamic_memory) => dynamic_memory.as_slice_mut(),
|
||||
MemoryStorage::Static(ref mut static_memory) => static_memory.as_slice_mut(),
|
||||
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||
};
|
||||
|
||||
let bytes_size = values.len() * mem::size_of::<T>();
|
||||
|
||||
if offset + bytes_size <= mem_slice.len() {
|
||||
let u8_buffer =
|
||||
unsafe { slice::from_raw_parts(values.as_ptr() as *const u8, bytes_size) };
|
||||
mem_slice[offset..offset + bytes_size].copy_from_slice(u8_buffer);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn direct_access<T: ValueType, F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&[T]) -> R,
|
||||
{
|
||||
let borrow_ref = self.storage.borrow();
|
||||
let memory_storage = &borrow_ref.0;
|
||||
|
||||
let mem_slice = match memory_storage {
|
||||
MemoryStorage::Dynamic(ref dynamic_memory) => dynamic_memory.as_slice(),
|
||||
MemoryStorage::Static(ref static_memory) => static_memory.as_slice(),
|
||||
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||
};
|
||||
|
||||
let t_buffer = unsafe {
|
||||
slice::from_raw_parts(
|
||||
mem_slice.as_ptr() as *const T,
|
||||
mem_slice.len() / mem::size_of::<T>(),
|
||||
)
|
||||
};
|
||||
|
||||
f(t_buffer)
|
||||
}
|
||||
|
||||
pub fn direct_access_mut<T: ValueType, F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&mut [T]) -> R,
|
||||
{
|
||||
let mut borrow_ref = self.storage.borrow_mut();
|
||||
let memory_storage = &mut borrow_ref.0;
|
||||
|
||||
let mem_slice = match memory_storage {
|
||||
MemoryStorage::Dynamic(ref mut dynamic_memory) => dynamic_memory.as_slice_mut(),
|
||||
MemoryStorage::Static(ref mut static_memory) => static_memory.as_slice_mut(),
|
||||
MemoryStorage::SharedStatic(_) => panic!("cannot slice a shared memory"),
|
||||
};
|
||||
|
||||
let t_buffer = unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
mem_slice.as_mut_ptr() as *mut T,
|
||||
mem_slice.len() / mem::size_of::<T>(),
|
||||
)
|
||||
};
|
||||
|
||||
f(t_buffer)
|
||||
}
|
||||
|
||||
pub fn vm_local_memory(&mut self) -> *mut vm::LocalMemory {
|
||||
&mut *self.storage.borrow_mut().1
|
||||
pub(crate) fn vm_local_memory(&self) -> *mut vm::LocalMemory {
|
||||
self.memory.vm_local_memory()
|
||||
}
|
||||
}
|
||||
|
||||
impl IsExport for Memory {
|
||||
impl IsExport for Memory<Unshared> {
|
||||
fn to_export(&self) -> Export {
|
||||
Export::Memory(self.clone())
|
||||
Export::Memory(MemoryVariant::Unshared(self.clone()))
|
||||
}
|
||||
}
|
||||
impl IsExport for Memory<Shared> {
|
||||
fn to_export(&self) -> Export {
|
||||
Export::Memory(MemoryVariant::Shared(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Memory {
|
||||
impl<S> Clone for Memory<S>
|
||||
where
|
||||
S: SharedPolicy,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
desc: self.desc,
|
||||
storage: Rc::clone(&self.storage),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MemoryStorage {
|
||||
Dynamic(Box<DynamicMemory>),
|
||||
Static(Box<StaticMemory>),
|
||||
SharedStatic(Box<SharedStaticMemory>),
|
||||
}
|
||||
|
||||
impl MemoryStorage {
|
||||
pub fn to_type(&self) -> MemoryType {
|
||||
match self {
|
||||
MemoryStorage::Dynamic(_) => MemoryType::Dynamic,
|
||||
MemoryStorage::Static(_) => MemoryType::Static,
|
||||
MemoryStorage::SharedStatic(_) => MemoryType::SharedStatic,
|
||||
memory: self.memory.clone(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,8 +188,7 @@ impl MemoryType {
|
||||
pub fn guard_size(self) -> u64 {
|
||||
match self {
|
||||
MemoryType::Dynamic => DYNAMIC_GUARD_SIZE as u64,
|
||||
MemoryType::Static => SAFE_STATIC_GUARD_SIZE as u64,
|
||||
MemoryType::SharedStatic => SAFE_STATIC_GUARD_SIZE as u64,
|
||||
MemoryType::Static | MemoryType::SharedStatic => SAFE_STATIC_GUARD_SIZE as u64,
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,13 +196,15 @@ impl MemoryType {
|
||||
pub fn bounds(self) -> Option<u64> {
|
||||
match self {
|
||||
MemoryType::Dynamic => None,
|
||||
MemoryType::Static => Some(SAFE_STATIC_HEAP_SIZE as u64),
|
||||
MemoryType::SharedStatic => Some(SAFE_STATIC_HEAP_SIZE as u64),
|
||||
MemoryType::Static | MemoryType::SharedStatic => Some(SAFE_STATIC_HEAP_SIZE as u64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Memory {
|
||||
impl<S> fmt::Debug for Memory<S>
|
||||
where
|
||||
S: SharedPolicy,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Memory")
|
||||
.field("desc", &self.desc)
|
||||
@ -301,3 +212,148 @@ impl fmt::Debug for Memory {
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MemoryVariant {
|
||||
Unshared(Memory<Unshared>),
|
||||
Shared(Memory<Shared>),
|
||||
}
|
||||
|
||||
enum UnsharedMemoryStorage {
|
||||
Dynamic(Box<DynamicMemory>),
|
||||
Static(Box<StaticMemory>),
|
||||
}
|
||||
|
||||
pub struct UnsharedMemory {
|
||||
internal: Rc<UnsharedMemoryInternal>,
|
||||
}
|
||||
|
||||
struct UnsharedMemoryInternal {
|
||||
storage: RefCell<UnsharedMemoryStorage>,
|
||||
local: Cell<vm::LocalMemory>,
|
||||
}
|
||||
|
||||
impl<'a> MemoryImpl<'a> for UnsharedMemory {
|
||||
type Access = Ref<'a, [u8]>;
|
||||
type AccessMut = RefMut<'a, [u8]>;
|
||||
|
||||
fn new(desc: MemoryDescriptor) -> Result<Self, CreationError> {
|
||||
let mut local = vm::LocalMemory {
|
||||
base: ptr::null_mut(),
|
||||
bound: 0,
|
||||
memory: ptr::null_mut(),
|
||||
};
|
||||
|
||||
let storage = match desc.memory_type() {
|
||||
MemoryType::Dynamic => {
|
||||
UnsharedMemoryStorage::Dynamic(DynamicMemory::new(desc, &mut local)?)
|
||||
}
|
||||
MemoryType::Static => {
|
||||
UnsharedMemoryStorage::Static(StaticMemory::new(desc, &mut local)?)
|
||||
}
|
||||
MemoryType::SharedStatic => panic!("attempting to create shared unshared memory"),
|
||||
};
|
||||
|
||||
Ok(UnsharedMemory {
|
||||
internal: Rc::new(UnsharedMemoryInternal {
|
||||
storage: RefCell::new(storage),
|
||||
local: Cell::new(local),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
fn grow(&self, delta: Pages) -> Option<Pages> {
|
||||
let mut storage = self.internal.storage.borrow_mut();
|
||||
|
||||
let mut local = self.internal.local.get();
|
||||
|
||||
let pages = match &mut *storage {
|
||||
UnsharedMemoryStorage::Dynamic(dynamic_memory) => {
|
||||
dynamic_memory.grow(delta, &mut local)
|
||||
}
|
||||
UnsharedMemoryStorage::Static(static_memory) => static_memory.grow(delta, &mut local),
|
||||
};
|
||||
|
||||
self.internal.local.set(local);
|
||||
|
||||
pages
|
||||
}
|
||||
|
||||
fn size(&self) -> Pages {
|
||||
let storage = self.internal.storage.borrow();
|
||||
|
||||
match &*storage {
|
||||
UnsharedMemoryStorage::Dynamic(ref dynamic_memory) => dynamic_memory.size(),
|
||||
UnsharedMemoryStorage::Static(ref static_memory) => static_memory.size(),
|
||||
}
|
||||
}
|
||||
|
||||
fn vm_local_memory(&self) -> *mut vm::LocalMemory {
|
||||
self.internal.local.as_ptr()
|
||||
}
|
||||
|
||||
fn access(&'a self) -> Ref<'a, [u8]> {
|
||||
Ref::map(
|
||||
self.internal.storage.borrow(),
|
||||
|memory_storage| match memory_storage {
|
||||
UnsharedMemoryStorage::Dynamic(dynamic_memory) => dynamic_memory.as_slice(),
|
||||
UnsharedMemoryStorage::Static(static_memory) => static_memory.as_slice(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn access_mut(&'a self) -> RefMut<'a, [u8]> {
|
||||
RefMut::map(
|
||||
self.internal.storage.borrow_mut(),
|
||||
|memory_storage| match memory_storage {
|
||||
UnsharedMemoryStorage::Dynamic(dynamic_memory) => dynamic_memory.as_slice_mut(),
|
||||
UnsharedMemoryStorage::Static(static_memory) => static_memory.as_slice_mut(),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for UnsharedMemory {
|
||||
fn clone(&self) -> Self {
|
||||
UnsharedMemory {
|
||||
internal: Rc::clone(&self.internal),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SharedMemory {}
|
||||
|
||||
impl<'a> MemoryImpl<'a> for SharedMemory {
|
||||
type Access = Vec<u8>;
|
||||
type AccessMut = Vec<u8>;
|
||||
|
||||
fn new(_desc: MemoryDescriptor) -> Result<Self, CreationError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn grow(&self, _delta: Pages) -> Option<Pages> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn size(&self) -> Pages {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn vm_local_memory(&self) -> *mut vm::LocalMemory {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn access(&self) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn access_mut(&self) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for SharedMemory {
|
||||
fn clone(&self) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
pub use crate::backing::{ImportBacking, LocalBacking};
|
||||
use crate::{
|
||||
memory::Memory,
|
||||
memory::{Memory, SharedPolicy},
|
||||
module::ModuleInner,
|
||||
structures::TypedIndex,
|
||||
types::{LocalOrImport, MemoryIndex},
|
||||
@ -106,24 +106,30 @@ impl Ctx {
|
||||
/// ```
|
||||
/// # use wasmer_runtime_core::{
|
||||
/// # vm::Ctx,
|
||||
/// # memory::Memory,
|
||||
/// # };
|
||||
/// fn read_memory(ctx: &Ctx) -> u8 {
|
||||
/// let first_memory = ctx.memory(0);
|
||||
/// let first_memory: &Memory = ctx.memory(0);
|
||||
/// // Read the first byte of that linear memory.
|
||||
/// first_memory.read(0).unwrap()
|
||||
/// first_memory.access()[0]
|
||||
/// }
|
||||
/// ```
|
||||
pub fn memory<'a>(&'a self, mem_index: u32) -> &'a Memory {
|
||||
pub fn memory<'a, S>(&'a self, mem_index: u32) -> &'a Memory<S>
|
||||
where
|
||||
S: SharedPolicy,
|
||||
{
|
||||
let module = unsafe { &*self.module };
|
||||
let mem_index = MemoryIndex::new(mem_index as usize);
|
||||
match mem_index.local_or_import(module) {
|
||||
LocalOrImport::Local(local_mem_index) => unsafe {
|
||||
let local_backing = &*self.local_backing;
|
||||
&local_backing.memories[local_mem_index]
|
||||
let mem_variant = &local_backing.memories[local_mem_index];
|
||||
S::transform_variant(mem_variant)
|
||||
},
|
||||
LocalOrImport::Import(import_mem_index) => unsafe {
|
||||
let import_backing = &*self.import_backing;
|
||||
&import_backing.memories[import_mem_index]
|
||||
let mem_variant = &import_backing.memories[import_mem_index];
|
||||
S::transform_variant(mem_variant)
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -195,7 +201,7 @@ impl ImportedFunc {
|
||||
}
|
||||
|
||||
/// Definition of a table used by the VM. (obviously)
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct LocalTable {
|
||||
/// pointer to the elements in the table.
|
||||
@ -222,7 +228,7 @@ impl LocalTable {
|
||||
}
|
||||
|
||||
/// Definition of a memory used by the VM.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct LocalMemory {
|
||||
/// Pointer to the bottom of this linear memory.
|
||||
@ -251,7 +257,7 @@ impl LocalMemory {
|
||||
}
|
||||
|
||||
/// Definition of a global used by the VM.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct LocalGlobal {
|
||||
pub data: u64,
|
||||
@ -277,7 +283,7 @@ impl LocalGlobal {
|
||||
pub struct SigId(pub u32);
|
||||
|
||||
/// Caller-checked anyfunc
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Anyfunc {
|
||||
pub func: *const Func,
|
||||
|
Reference in New Issue
Block a user