297 lines
7.6 KiB
Rust
Raw Normal View History

use crate::{
2019-01-29 15:44:15 -08:00
error::CreationError,
export::Export,
import::IsExport,
memory::dynamic::DYNAMIC_GUARD_SIZE,
memory::static_::{SAFE_STATIC_GUARD_SIZE, SAFE_STATIC_HEAP_SIZE},
2019-02-04 23:07:58 -08:00
types::{MemoryDescriptor, ValueType},
2019-01-29 15:44:15 -08:00
units::Pages,
vm,
};
2019-02-04 15:07:32 -08:00
use std::{
cell::{Cell, Ref, RefCell, RefMut},
fmt,
marker::PhantomData,
2019-02-04 23:07:58 -08:00
mem,
ops::{Bound, Deref, DerefMut, Index, RangeBounds},
2019-02-04 15:07:32 -08:00
ptr,
rc::Rc,
2019-02-04 23:07:58 -08:00
slice,
2019-02-04 15:07:32 -08:00
};
2019-02-04 23:07:58 -08:00
pub use self::atomic::Atomic;
pub use self::dynamic::DynamicMemory;
pub use self::static_::{SharedStaticMemory, StaticMemory};
2019-02-04 23:07:58 -08:00
pub use self::view::{Atomically, MemoryView};
2019-02-04 23:07:58 -08:00
mod atomic;
mod dynamic;
mod static_;
2019-02-04 23:07:58 -08:00
mod view;
2019-02-04 23:07:58 -08:00
#[derive(Clone)]
enum MemoryVariant {
Unshared(UnsharedMemory),
Shared(SharedMemory),
2019-02-04 15:07:32 -08:00
}
2019-02-04 23:07:58 -08:00
#[derive(Clone)]
pub struct Memory {
2019-01-29 13:04:42 -08:00
desc: MemoryDescriptor,
2019-02-04 23:07:58 -08:00
variant: MemoryVariant,
}
2019-02-04 23:07:58 -08:00
impl Memory {
2019-01-29 14:15:59 -08:00
/// Create a new `Memory` from a [`MemoryDescriptor`]
2019-01-29 15:44:15 -08:00
///
2019-01-29 14:15:59 -08:00
/// [`MemoryDescriptor`]: struct.MemoryDescriptor.html
2019-01-29 15:44:15 -08:00
///
2019-01-29 14:15:59 -08:00
/// Usage:
2019-01-29 15:44:15 -08:00
///
2019-01-29 14:15:59 -08:00
/// ```
/// # use wasmer_runtime_core::types::MemoryDescriptor;
/// # use wasmer_runtime_core::memory::Memory;
/// # use wasmer_runtime_core::error::Result;
2019-01-29 15:44:15 -08:00
/// # use wasmer_runtime_core::units::Pages;
2019-01-29 14:15:59 -08:00
/// # fn create_memory() -> Result<()> {
/// let descriptor = MemoryDescriptor {
2019-01-29 15:44:15 -08:00
/// minimum: Pages(10),
2019-01-29 14:15:59 -08:00
/// maximum: None,
/// shared: false,
/// };
2019-01-29 15:44:15 -08:00
///
2019-02-04 23:07:58 -08:00
/// let memory = Memory::new(descriptor)?;
2019-01-29 14:15:59 -08:00
/// # Ok(())
/// # }
/// ```
2019-02-04 23:07:58 -08:00
pub fn new(desc: MemoryDescriptor) -> Result<Self, CreationError> {
let variant = if !desc.shared {
MemoryVariant::Unshared(UnsharedMemory::new(desc)?)
} else {
MemoryVariant::Shared(SharedMemory::new(desc)?)
};
Ok(Memory { desc, variant })
}
2019-01-29 14:15:59 -08:00
/// Return the [`MemoryDescriptor`] that this memory
/// was created with.
2019-01-29 15:44:15 -08:00
///
2019-01-29 14:15:59 -08:00
/// [`MemoryDescriptor`]: struct.MemoryDescriptor.html
2019-01-29 13:04:42 -08:00
pub fn descriptor(&self) -> MemoryDescriptor {
self.desc
}
2019-01-29 14:15:59 -08:00
/// Grow this memory by the specfied number of pages.
2019-02-04 15:07:32 -08:00
pub fn grow(&self, delta: Pages) -> Option<Pages> {
2019-02-04 23:07:58 -08:00
match &self.variant {
MemoryVariant::Unshared(unshared_mem) => unshared_mem.grow(delta),
MemoryVariant::Shared(shared_mem) => shared_mem.grow(delta),
}
}
2019-01-29 14:15:59 -08:00
/// The size, in wasm pages, of this memory.
2019-01-29 15:44:15 -08:00
pub fn size(&self) -> Pages {
2019-02-04 23:07:58 -08:00
match &self.variant {
MemoryVariant::Unshared(unshared_mem) => unshared_mem.size(),
MemoryVariant::Shared(shared_mem) => shared_mem.size(),
}
}
2019-02-04 23:07:58 -08:00
pub fn view<T: ValueType, R: RangeBounds<usize>>(&self, range: R) -> Option<MemoryView<T>> {
let vm::LocalMemory {
base,
bound,
memory: _,
} = unsafe { *self.vm_local_memory() };
let range_start = match range.start_bound() {
Bound::Included(start) => *start,
Bound::Excluded(start) => *start + 1,
Bound::Unbounded => 0,
};
let range_end = match range.end_bound() {
Bound::Included(end) => *end + 1,
Bound::Excluded(end) => *end,
Bound::Unbounded => bound as usize,
};
let length = range_end - range_start;
let size_in_bytes = mem::size_of::<T>() * length;
if range_end < range_start || range_start + size_in_bytes >= bound {
return None;
}
Some(unsafe { MemoryView::new(base as _, length as u32) })
2019-01-29 12:12:37 -08:00
}
2019-02-04 23:07:58 -08:00
pub fn shared(self) -> Option<SharedMemory> {
if self.desc.shared {
Some(SharedMemory { desc: self.desc })
} else {
None
}
2019-01-29 12:12:37 -08:00
}
2019-02-04 15:07:32 -08:00
pub(crate) fn vm_local_memory(&self) -> *mut vm::LocalMemory {
2019-02-04 23:07:58 -08:00
match &self.variant {
MemoryVariant::Unshared(unshared_mem) => unshared_mem.vm_local_memory(),
MemoryVariant::Shared(shared_mem) => unimplemented!(),
}
2019-01-28 10:59:05 -08:00
}
2019-02-04 15:07:32 -08:00
}
2019-01-28 10:59:05 -08:00
2019-02-04 23:07:58 -08:00
impl IsExport for Memory {
2019-02-02 15:58:33 -08:00
fn to_export(&self) -> Export {
2019-02-04 23:07:58 -08:00
Export::Memory(self.clone())
}
}
2019-02-04 23:07:58 -08:00
impl fmt::Debug for Memory {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Memory")
.field("desc", &self.desc)
.field("size", &self.size())
.finish()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MemoryType {
Dynamic,
Static,
SharedStatic,
}
impl MemoryType {
#[doc(hidden)]
pub fn guard_size(self) -> u64 {
match self {
MemoryType::Dynamic => DYNAMIC_GUARD_SIZE as u64,
2019-02-04 15:07:32 -08:00
MemoryType::Static | MemoryType::SharedStatic => SAFE_STATIC_GUARD_SIZE as u64,
}
}
#[doc(hidden)]
pub fn bounds(self) -> Option<u64> {
match self {
MemoryType::Dynamic => None,
2019-02-04 15:07:32 -08:00
MemoryType::Static | MemoryType::SharedStatic => Some(SAFE_STATIC_HEAP_SIZE as u64),
}
}
}
2019-02-04 15:07:32 -08:00
enum UnsharedMemoryStorage {
Dynamic(Box<DynamicMemory>),
Static(Box<StaticMemory>),
}
pub struct UnsharedMemory {
internal: Rc<UnsharedMemoryInternal>,
}
struct UnsharedMemoryInternal {
storage: RefCell<UnsharedMemoryStorage>,
local: Cell<vm::LocalMemory>,
}
2019-02-04 23:07:58 -08:00
impl UnsharedMemory {
pub fn new(desc: MemoryDescriptor) -> Result<Self, CreationError> {
2019-02-04 15:07:32 -08:00
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),
}),
})
}
2019-02-04 23:07:58 -08:00
pub fn grow(&self, delta: Pages) -> Option<Pages> {
2019-02-04 15:07:32 -08:00
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
}
2019-02-04 23:07:58 -08:00
pub fn size(&self) -> Pages {
2019-02-04 15:07:32 -08:00
let storage = self.internal.storage.borrow();
match &*storage {
UnsharedMemoryStorage::Dynamic(ref dynamic_memory) => dynamic_memory.size(),
UnsharedMemoryStorage::Static(ref static_memory) => static_memory.size(),
}
}
2019-02-04 23:07:58 -08:00
pub(crate) fn vm_local_memory(&self) -> *mut vm::LocalMemory {
2019-02-04 15:07:32 -08:00
self.internal.local.as_ptr()
}
}
impl Clone for UnsharedMemory {
fn clone(&self) -> Self {
UnsharedMemory {
internal: Rc::clone(&self.internal),
}
}
}
2019-02-04 23:07:58 -08:00
pub struct SharedMemory {
desc: MemoryDescriptor,
}
2019-02-04 15:07:32 -08:00
2019-02-04 23:07:58 -08:00
impl SharedMemory {
fn new(desc: MemoryDescriptor) -> Result<Self, CreationError> {
Ok(Self { desc })
2019-02-04 15:07:32 -08:00
}
2019-02-04 23:07:58 -08:00
pub fn grow(&self, _delta: Pages) -> Option<Pages> {
2019-02-04 15:07:32 -08:00
unimplemented!()
}
2019-02-04 23:07:58 -08:00
pub fn size(&self) -> Pages {
2019-02-04 15:07:32 -08:00
unimplemented!()
}
2019-02-04 23:07:58 -08:00
pub unsafe fn as_slice(&self) -> &[u8] {
2019-02-04 15:07:32 -08:00
unimplemented!()
}
2019-02-04 23:07:58 -08:00
pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
2019-02-04 15:07:32 -08:00
unimplemented!()
}
}
impl Clone for SharedMemory {
fn clone(&self) -> Self {
unimplemented!()
}
}