From 358adb334a69cd67e54c4c44e7e39a72dd7e77af Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Mon, 15 Jul 2019 23:22:59 +0300 Subject: [PATCH] Cache bytebuf --- src/lib.rs | 2 +- src/memory/mmap_bytebuf.rs | 29 ++++-------- src/memory/mod.rs | 93 ++++++++++++++++++++++++++------------ 3 files changed, 75 insertions(+), 49 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d14e47c..3080272 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -404,7 +404,7 @@ pub use self::func::{FuncInstance, FuncInvocation, FuncRef, ResumableError}; pub use self::global::{GlobalInstance, GlobalRef}; pub use self::host::{Externals, HostError, NopExternals, RuntimeArgs}; pub use self::imports::{ImportResolver, ImportsBuilder, ModuleImportResolver}; -pub use self::memory::{MemoryBackend, MemoryInstance, MemoryRef, LINEAR_MEMORY_PAGE_SIZE}; +pub use self::memory::{MemoryBackend, ByteBuf, MemoryInstance, MemoryRef, LINEAR_MEMORY_PAGE_SIZE}; pub use self::module::{ExternVal, ModuleInstance, ModuleRef, NotStartedModuleRef}; pub use self::runner::{StackRecycler, DEFAULT_CALL_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT}; pub use self::table::{TableInstance, TableRef}; diff --git a/src/memory/mmap_bytebuf.rs b/src/memory/mmap_bytebuf.rs index aa3a6b5..f3c1503 100644 --- a/src/memory/mmap_bytebuf.rs +++ b/src/memory/mmap_bytebuf.rs @@ -7,7 +7,7 @@ use std::ptr::{self, NonNull}; use std::slice; -use super::MemoryBackend; +use super::{MemoryBackend, ByteBuf}; struct Mmap { /// The pointer that points to the start of the mapping. @@ -132,11 +132,11 @@ impl MmapByteBuf { } impl MemoryBackend for MmapByteBuf { - fn alloc(&mut self, initial: usize, _maximum: usize) -> Result<(), &'static str> { + fn alloc(&mut self, initial: usize, _maximum: Option) -> Result { self.realloc(initial) } - fn realloc(&mut self, new_len: usize) -> Result<(), &'static str> { + fn realloc(&mut self, new_len: usize) -> Result { let new_mmap = if new_len == 0 { None } else { @@ -150,27 +150,16 @@ impl MemoryBackend for MmapByteBuf { Some(new_mmap) }; + let bytebuf = ByteBuf { + ptr: new_mmap.as_ref().map(|m| m.ptr.as_ptr()).unwrap_or(NonNull::dangling().as_ptr()), + len: new_mmap.as_ref().map(|m| m.len).unwrap_or(0), + }; self.mmap = new_mmap; - Ok(()) - } - - fn len(&self) -> usize { - self.mmap.as_ref().map(|m| m.len).unwrap_or(0) - } - - fn as_slice(&self) -> &[u8] { - self.mmap.as_ref().map(|m| m.as_slice()).unwrap_or(&[]) - } - - fn as_slice_mut(&mut self) -> &mut [u8] { - self.mmap - .as_mut() - .map(|m| m.as_slice_mut()) - .unwrap_or(&mut []) + Ok(bytebuf) } fn erase(&mut self) -> Result<(), &'static str> { - let len = self.len(); + let len = self.mmap.as_ref().map(|m| m.len).unwrap_or(0); if len > 0 { // The order is important. // diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 8d6ed56..1e47962 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -3,6 +3,7 @@ use core::{ cell::{Cell, RefCell}, cmp, fmt, ops::Range, + slice, u32, }; use memory_units::{Bytes, Pages, RoundUpTo}; @@ -43,12 +44,32 @@ impl ::core::ops::Deref for MemoryRef { } } +pub struct ByteBuf { + pub ptr: *mut u8, + pub len: usize, +} + +impl ByteBuf { + pub fn as_slice(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self.ptr, self.len) + } + } + + pub fn as_slice_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self.ptr, self.len) + } + } + + pub fn len(&self) -> usize { + self.len + } +} + pub trait MemoryBackend { - fn alloc(&mut self, initial: usize, maximum: usize) -> Result<(), &'static str>; - fn realloc(&mut self, new_len: usize) -> Result<(), &'static str>; - fn len(&self) -> usize; - fn as_slice(&self) -> &[u8]; - fn as_slice_mut(&mut self) -> &mut [u8]; + fn alloc(&mut self, initial: usize, maximum: Option) -> Result; + fn realloc(&mut self, new_len: usize) -> Result; fn erase(&mut self) -> Result<(), &'static str>; } @@ -69,7 +90,8 @@ pub struct MemoryInstance { /// Memory limits. limits: ResizableLimits, /// Linear memory buffer with lazy allocation. - buffer: RefCell>, + backend: RefCell>, + bytebuf: RefCell, initial: Pages, current_size: Cell, maximum: Option, @@ -79,7 +101,7 @@ impl fmt::Debug for MemoryInstance { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("MemoryInstance") .field("limits", &self.limits) - .field("buffer.len", &self.buffer.borrow().len()) + .field("buffer.len", &self.bytebuf.borrow().len()) .field("maximum", &self.maximum) .field("initial", &self.initial) .finish() @@ -151,19 +173,33 @@ impl MemoryInstance { let limits = ResizableLimits::new(initial.0 as u32, maximum.map(|p| p.0 as u32)); let initial_size: Bytes = initial.into(); - let bytebuf = MmapByteBuf::new(initial_size.0).map_err(|err| Error::Memory(err.to_string()))?; + let maximum_size: Option = maximum.map(|m| m.into()); + let mut backend = MmapByteBuf::new(initial_size.0).map_err(|err| Error::Memory(err.to_string()))?; + let bytebuf = backend.alloc( + initial_size.0, + maximum_size.map(|m| m.0), + ).map_err(|err| Error::Memory(err.to_string()))?; Ok(MemoryInstance { limits: limits, - buffer: RefCell::new(Box::new(bytebuf)), + backend: RefCell::new(Box::new(backend)), + bytebuf: RefCell::new(bytebuf), initial: initial, current_size: Cell::new(initial_size.0), maximum: maximum, }) } - pub fn set_backend(&self, backend: Box) { - *self.buffer.borrow_mut() = backend; + pub fn set_backend(&self, mut backend: Box) { + let initial_size: Bytes = self.initial.into(); + let maximum_size: Option = self.maximum.map(|m| m.into()); + + let bytebuf = backend.alloc( + initial_size.0, + maximum_size.map(|m| m.0), + ).unwrap(); + *self.backend.borrow_mut() = backend; + *self.bytebuf.borrow_mut() = bytebuf; } /// Return linear memory limits. @@ -204,12 +240,12 @@ impl MemoryInstance { /// ); /// ``` pub fn current_size(&self) -> Pages { - Bytes(self.buffer.borrow().len()).round_up_to() + Bytes(self.bytebuf.borrow().len()).round_up_to() } /// Get value from memory at given offset. pub fn get_value(&self, offset: u32) -> Result { - let mut buffer = self.buffer.borrow_mut(); + let mut buffer = self.bytebuf.borrow_mut(); let region = self.checked_region(&mut buffer, offset as usize, ::core::mem::size_of::())?; Ok( @@ -225,7 +261,7 @@ impl MemoryInstance { /// /// [`get_into`]: #method.get_into pub fn get(&self, offset: u32, size: usize) -> Result, Error> { - let mut buffer = self.buffer.borrow_mut(); + let mut buffer = self.bytebuf.borrow_mut(); let region = self.checked_region(&mut buffer, offset as usize, size)?; Ok(buffer.as_slice_mut()[region.range()].to_vec()) @@ -237,7 +273,7 @@ impl MemoryInstance { /// /// Returns `Err` if the specified region is out of bounds. pub fn get_into(&self, offset: u32, target: &mut [u8]) -> Result<(), Error> { - let mut buffer = self.buffer.borrow_mut(); + let mut buffer = self.bytebuf.borrow_mut(); let region = self.checked_region(&mut buffer, offset as usize, target.len())?; target.copy_from_slice(&buffer.as_slice_mut()[region.range()]); @@ -247,7 +283,7 @@ impl MemoryInstance { /// Copy data in the memory at given offset. pub fn set(&self, offset: u32, value: &[u8]) -> Result<(), Error> { - let mut buffer = self.buffer.borrow_mut(); + let mut buffer = self.bytebuf.borrow_mut(); let range = self .checked_region(&mut buffer, offset as usize, value.len())? .range(); @@ -259,7 +295,7 @@ impl MemoryInstance { /// Copy value in the memory at given offset. pub fn set_value(&self, offset: u32, value: T) -> Result<(), Error> { - let mut buffer = self.buffer.borrow_mut(); + let mut buffer = self.bytebuf.borrow_mut(); let range = self .checked_region(&mut buffer, offset as usize, ::core::mem::size_of::())? .range(); @@ -297,10 +333,11 @@ impl MemoryInstance { } let new_buffer_length: Bytes = new_size.into(); - self.buffer + let bytebuf = self.backend .borrow_mut() .realloc(new_buffer_length.0) .map_err(|err| Error::Memory(err.to_string()))?; + *self.bytebuf.borrow_mut() = bytebuf; self.current_size.set(new_buffer_length.0); @@ -309,7 +346,7 @@ impl MemoryInstance { fn checked_region( &self, - buffer: &mut Box, + buffer: &mut ByteBuf, offset: usize, size: usize, ) -> Result { @@ -337,7 +374,7 @@ impl MemoryInstance { fn checked_region_pair( &self, - buffer: &mut Box, + buffer: &mut ByteBuf, offset1: usize, size1: usize, offset2: usize, @@ -395,7 +432,7 @@ impl MemoryInstance { /// /// Returns `Err` if either of specified regions is out of bounds. pub fn copy(&self, src_offset: usize, dst_offset: usize, len: usize) -> Result<(), Error> { - let mut buffer = self.buffer.borrow_mut(); + let mut buffer = self.bytebuf.borrow_mut(); let (read_region, write_region) = self.checked_region_pair(&mut buffer, src_offset, len, dst_offset, len)?; @@ -428,7 +465,7 @@ impl MemoryInstance { dst_offset: usize, len: usize, ) -> Result<(), Error> { - let mut buffer = self.buffer.borrow_mut(); + let mut buffer = self.bytebuf.borrow_mut(); let (read_region, write_region) = self.checked_region_pair(&mut buffer, src_offset, len, dst_offset, len)?; @@ -468,8 +505,8 @@ impl MemoryInstance { // Because memory references point to different memory instances, it is safe to `borrow_mut` // both buffers at once (modulo `with_direct_access_mut`). - let mut src_buffer = src.buffer.borrow_mut(); - let mut dst_buffer = dst.buffer.borrow_mut(); + let mut src_buffer = src.bytebuf.borrow_mut(); + let mut dst_buffer = dst.bytebuf.borrow_mut(); let src_range = src .checked_region(&mut src_buffer, src_offset, len)? @@ -491,7 +528,7 @@ impl MemoryInstance { /// /// Returns `Err` if the specified region is out of bounds. pub fn clear(&self, offset: usize, new_val: u8, len: usize) -> Result<(), Error> { - let mut buffer = self.buffer.borrow_mut(); + let mut buffer = self.bytebuf.borrow_mut(); let range = self.checked_region(&mut buffer, offset, len)?.range(); @@ -514,7 +551,7 @@ impl MemoryInstance { /// /// Might be useful for some optimization shenanigans. pub fn erase(&self) -> Result<(), Error> { - self.buffer + self.backend .borrow_mut() .erase() .map_err(|err| Error::Memory(err.to_string())) @@ -530,7 +567,7 @@ impl MemoryInstance { /// [`set`]: #method.get /// [`clear`]: #method.set pub fn with_direct_access R>(&self, f: F) -> R { - let buf = self.buffer.borrow(); + let buf = self.bytebuf.borrow(); f(buf.as_slice()) } @@ -544,7 +581,7 @@ impl MemoryInstance { /// [`get`]: #method.get /// [`set`]: #method.set pub fn with_direct_access_mut R>(&self, f: F) -> R { - let mut buf = self.buffer.borrow_mut(); + let mut buf = self.bytebuf.borrow_mut(); f(buf.as_slice_mut()) } }