diff --git a/lib/runtime-core/examples/simple/main.rs b/lib/runtime-core/examples/simple/main.rs index e2050e8cd..37e9d5e13 100644 --- a/lib/runtime-core/examples/simple/main.rs +++ b/lib/runtime-core/examples/simple/main.rs @@ -58,9 +58,14 @@ fn main() -> Result<()> { Ok(()) } -extern "C" fn print_num(n: i32, _vmctx: &mut vm::Ctx) -> i32 { +extern "C" fn print_num(n: i32, ctx: &mut vm::Ctx) -> i32 { println!("print_num({})", n); - n + 1 + + let memory = ctx.memory(0); + + let a: i32 = memory.read(0).unwrap(); + + a + n + 1 } static IMPORT_MODULE: &str = r#" diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index e82b8d181..1f3847c8c 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -107,7 +107,7 @@ impl LocalBacking { assert!(memory_desc.min as usize * WASM_PAGE_SIZE >= data_top); let mem = &memories[local_memory_index]; - mem.set(init_base as u32, &init.data).unwrap(); + mem.write_many(init_base as u32, &init.data).unwrap(); } LocalOrImport::Import(imported_memory_index) => { // Write the initialization data to the memory that diff --git a/lib/runtime-core/src/memory/mod.rs b/lib/runtime-core/src/memory/mod.rs index f29ae1064..4e25c359e 100644 --- a/lib/runtime-core/src/memory/mod.rs +++ b/lib/runtime-core/src/memory/mod.rs @@ -71,7 +71,44 @@ impl Memory { } } - pub fn get(&self, offset: u32, count: usize) -> Result, ()> { + pub fn read(&self, offset: u32) -> Result { + 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::() <= mem_slice.len() { + T::from_le(&mem_slice[offset..]).map_err(|_| ()) + } else { + Err(()) + } + } + + pub fn write(&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::() <= mem_slice.len() { + value.into_le(&mut mem_slice[offset..]); + Ok(()) + } else { + Err(()) + } + } + + pub fn read_many(&self, offset: u32, count: usize) -> Result, ()> { let offset = offset as usize; let borrow_ref = self.storage.borrow(); let memory_storage = &borrow_ref.0; @@ -98,7 +135,7 @@ impl Memory { } } - pub fn set(&self, offset: u32, values: &[T]) -> Result<(), ()> { + pub fn write_many(&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; diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index 70e5f66d3..6d8c92f84 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -81,12 +81,12 @@ macro_rules! convert_value_impl { ($t:ty) => { impl ValueType for $t { fn into_le(self, buffer: &mut [u8]) { - buffer.copy_from_slice(&self.to_le_bytes()); + buffer[..mem::size_of::()].copy_from_slice(&self.to_le_bytes()); } fn from_le(buffer: &[u8]) -> Result { if buffer.len() >= mem::size_of::() { let mut array = [0u8; mem::size_of::()]; - array.copy_from_slice(buffer); + array.copy_from_slice(&buffer[..mem::size_of::()]); Ok(Self::from_le_bytes(array)) } else { Err(ValueError::BufferTooSmall) diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 2e58f82d4..d1fc2d3f4 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -1,10 +1,11 @@ pub use crate::backing::{ImportBacking, LocalBacking}; use crate::{ + memory::Memory, module::ModuleInner, structures::TypedIndex, types::{LocalOrImport, MemoryIndex}, }; -use std::{ffi::c_void, mem, ptr, slice}; +use std::{ffi::c_void, mem, ptr}; /// The context of the currently running WebAssembly instance. /// @@ -33,8 +34,8 @@ pub struct Ctx { /// A pointer to an array of imported functions, indexed by `FuncIndex`. pub(crate) imported_funcs: *mut ImportedFunc, - // pub(crate) local_backing: *mut LocalBacking, - // pub(crate) import_backing: *mut ImportBacking, + local_backing: *mut LocalBacking, + import_backing: *mut ImportBacking, module: *const ModuleInner, pub data: *mut c_void, @@ -58,8 +59,8 @@ impl Ctx { imported_globals: import_backing.vm_globals.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(), - // local_backing, - // import_backing, + local_backing, + import_backing, module, data: ptr::null_mut(), @@ -85,8 +86,8 @@ impl Ctx { imported_globals: import_backing.vm_globals.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(), - // local_backing, - // import_backing, + local_backing, + import_backing, module, data, @@ -109,54 +110,20 @@ impl Ctx { /// fn read_memory(ctx: &Ctx) -> u8 { /// let first_memory = ctx.memory(0); /// // Read the first byte of that linear memory. - /// first_memory[0] + /// first_memory.get(0) /// } /// ``` - pub fn memory<'a>(&'a self, mem_index: u32) -> &'a [u8] { + pub fn memory<'a>(&'a self, mem_index: u32) -> &'a Memory { 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_memory = &**self.memories.add(local_mem_index.index()); - slice::from_raw_parts(local_memory.base, local_memory.bound) + let local_backing = &*self.local_backing; + &local_backing.memories[local_mem_index] }, LocalOrImport::Import(import_mem_index) => unsafe { - let local_memory = &**self.imported_memories.add(import_mem_index.index()); - slice::from_raw_parts(local_memory.base, local_memory.bound) - }, - } - } - - /// This exposes the specified memory of the WebAssembly instance - /// as a mutable slice. - /// - /// WebAssembly will soon support multiple linear memories, so this - /// forces the user to specify. - /// - /// # Usage: - /// - /// ``` - /// # use wasmer_runtime_core::{ - /// # vm::Ctx, - /// # error::Result, - /// # }; - /// extern fn host_func(ctx: &mut Ctx) { - /// let first_memory = ctx.memory_mut(0); - /// // Set the first byte of that linear memory. - /// first_memory[0] = 42; - /// } - /// ``` - pub fn memory_mut<'a>(&'a mut self, mem_index: u32) -> &'a mut [u8] { - 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_memory = &**self.memories.add(local_mem_index.index()); - slice::from_raw_parts_mut(local_memory.base, local_memory.bound) - }, - LocalOrImport::Import(import_mem_index) => unsafe { - let local_memory = &**self.imported_memories.add(import_mem_index.index()); - slice::from_raw_parts_mut(local_memory.base, local_memory.bound) + let import_backing = &*self.import_backing; + &import_backing.memories[import_mem_index] }, } }