mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Add touch-ups to new memory api
This commit is contained in:
parent
f75006c062
commit
8a8290b155
@ -97,9 +97,7 @@ impl LocalBacking {
|
||||
assert!(memory_desc.minimum.bytes().0 >= data_top);
|
||||
|
||||
let mem = &memories[local_memory_index];
|
||||
for (mem_byte, data_byte) in mem
|
||||
.view(init_base..init_base + init.data.len())
|
||||
.unwrap()
|
||||
for (mem_byte, data_byte) in mem.view()[init_base..init_base + init.data.len()]
|
||||
.iter()
|
||||
.zip(init.data.iter())
|
||||
{
|
||||
|
@ -29,22 +29,22 @@ pub trait IntCast:
|
||||
macro_rules! intcast {
|
||||
($($type:ident)+) => {
|
||||
$(
|
||||
impl IntCast for Wrapping<$type> {
|
||||
impl IntCast for $type {
|
||||
type Public = $type;
|
||||
|
||||
fn from(u: usize) -> Self {
|
||||
Wrapping(u as $type)
|
||||
u as $type
|
||||
}
|
||||
fn to(self) -> usize {
|
||||
self.0 as usize
|
||||
self as usize
|
||||
}
|
||||
|
||||
fn new(p: $type) -> Self {
|
||||
Wrapping(p)
|
||||
p
|
||||
}
|
||||
|
||||
fn unwrap(self) -> $type {
|
||||
self.0
|
||||
self
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
@ -9,14 +9,9 @@ use crate::{
|
||||
vm,
|
||||
};
|
||||
use std::{
|
||||
cell::{Cell, Ref, RefCell, RefMut},
|
||||
fmt,
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
ops::{Bound, Deref, DerefMut, Index, RangeBounds},
|
||||
ptr,
|
||||
cell::{Cell, RefCell},
|
||||
fmt, mem, ptr,
|
||||
rc::Rc,
|
||||
slice,
|
||||
};
|
||||
|
||||
pub use self::atomic::Atomic;
|
||||
@ -35,6 +30,9 @@ enum MemoryVariant {
|
||||
Shared(SharedMemory),
|
||||
}
|
||||
|
||||
/// A shared or unshared wasm linear memory.
|
||||
///
|
||||
/// A `Memory` represents the memory used by a wasm instance.
|
||||
#[derive(Clone)]
|
||||
pub struct Memory {
|
||||
desc: MemoryDescriptor,
|
||||
@ -98,36 +96,53 @@ impl Memory {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn view<T: ValueType, R: RangeBounds<usize>>(&self, range: R) -> Option<MemoryView<T>> {
|
||||
/// Return a "view" of the currently accessible memory. By
|
||||
/// default, the view is unsyncronized, using regular memory
|
||||
/// accesses. You can force a memory view to use atomic accesses
|
||||
/// by calling the [`atomically`] method.
|
||||
///
|
||||
/// [`atomically`]: memory/struct.MemoryView.html#method.atomically
|
||||
///
|
||||
/// # Notes:
|
||||
///
|
||||
/// This method is safe (as in, it won't cause the host to crash or have UB),
|
||||
/// but it doesn't obey rust's rules involving data races, especially concurrent ones.
|
||||
/// Therefore, if this memory is shared between multiple threads, a single memory
|
||||
/// location can be mutated concurrently without synchronization.
|
||||
///
|
||||
/// # Usage:
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer_runtime_core::memory::{Memory, MemoryView};
|
||||
/// # use std::sync::atomic::Ordering;
|
||||
/// # fn view_memory(memory: Memory) {
|
||||
/// // Without synchronization.
|
||||
/// let view: MemoryView<u8> = memory.view();
|
||||
/// for byte in view[0x1000 .. 0x1010].iter().map(|cell| cell.get()) {
|
||||
/// println!("byte: {}", byte);
|
||||
/// }
|
||||
///
|
||||
/// // With synchronization.
|
||||
/// let atomic_view = view.atomically();
|
||||
/// for byte in atomic_view[0x1000 .. 0x1010].iter().map(|atom| atom.load(Ordering::SeqCst)) {
|
||||
/// println!("byte: {}", byte);
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn view<T: ValueType>(&self) -> MemoryView<T> {
|
||||
let vm::LocalMemory {
|
||||
base,
|
||||
bound,
|
||||
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 length = self.size().bytes().0 / mem::size_of::<T>();
|
||||
|
||||
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) })
|
||||
unsafe { MemoryView::new(base as _, length as u32) }
|
||||
}
|
||||
|
||||
/// Convert this memory to a shared memory if the shared flag
|
||||
/// is present in the description used to create it.
|
||||
pub fn shared(self) -> Option<SharedMemory> {
|
||||
if self.desc.shared {
|
||||
Some(SharedMemory { desc: self.desc })
|
||||
@ -139,7 +154,7 @@ impl Memory {
|
||||
pub(crate) fn vm_local_memory(&self) -> *mut vm::LocalMemory {
|
||||
match &self.variant {
|
||||
MemoryVariant::Unshared(unshared_mem) => unshared_mem.vm_local_memory(),
|
||||
MemoryVariant::Shared(shared_mem) => unimplemented!(),
|
||||
MemoryVariant::Shared(_) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> MemoryView<'a, T, NonAtomically> {
|
||||
pub fn atomically(self) -> MemoryView<'a, T, Atomically> {
|
||||
impl<'a, T: IntCast> MemoryView<'a, T, NonAtomically> {
|
||||
pub fn atomically(&self) -> MemoryView<'a, T, Atomically> {
|
||||
MemoryView {
|
||||
ptr: self.ptr,
|
||||
length: self.length,
|
||||
|
@ -106,12 +106,11 @@ impl Ctx {
|
||||
/// ```
|
||||
/// # use wasmer_runtime_core::{
|
||||
/// # vm::Ctx,
|
||||
/// # memory::Memory,
|
||||
/// # };
|
||||
/// fn read_memory(ctx: &Ctx) -> u8 {
|
||||
/// let first_memory: &Memory = ctx.memory(0);
|
||||
/// let first_memory = ctx.memory(0);
|
||||
/// // Read the first byte of that linear memory.
|
||||
/// first_memory.access()[0]
|
||||
/// first_memory.view()[0].get()
|
||||
/// }
|
||||
/// ```
|
||||
pub fn memory(&self, mem_index: u32) -> &Memory {
|
||||
|
Loading…
Reference in New Issue
Block a user