Create a grow error and refactor grow impl to return result (#191)

This commit is contained in:
Mackenzie Clark
2019-02-22 22:18:59 -08:00
committed by GitHub
parent fa596d2d23
commit 82eef13f41
13 changed files with 250 additions and 112 deletions

View File

@ -1,3 +1,4 @@
use crate::error::GrowError;
use crate::{
error::CreationError,
sys,
@ -14,9 +15,9 @@ pub const DYNAMIC_GUARD_SIZE: usize = 4096;
/// when first created. Over time, as it grows, it may reallocate to
/// a different location and size.
///
/// Dynamic memories are signifigantly faster to create than static
/// Dynamic memories are significantly faster to create than static
/// memories and use much less virtual memory, however, they require
/// the webassembly module to bounds-check memory accesses.
/// the WebAssembly module to bounds-check memory accesses.
///
/// While, a dynamic memory could use a vector of some sort as its
/// backing memory, we use mmap (or the platform-equivalent) to allow
@ -65,26 +66,29 @@ impl DynamicMemory {
self.current
}
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Option<Pages> {
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Result<Pages, GrowError> {
if delta == Pages(0) {
return Some(self.current);
return Ok(self.current);
}
let new_pages = self.current.checked_add(delta)?;
let new_pages = self.current.checked_add(delta).map_err(|e| e.into())?;
if let Some(max) = self.max {
if new_pages > max {
return None;
return Err(GrowError::ExceededMaxPagesForMemory(
new_pages.0 as usize,
max.0 as usize,
));
}
}
let mut new_memory =
sys::Memory::with_size(new_pages.bytes().0 + DYNAMIC_GUARD_SIZE).ok()?;
let mut new_memory = sys::Memory::with_size(new_pages.bytes().0 + DYNAMIC_GUARD_SIZE)
.map_err(|e| e.into())?;
unsafe {
new_memory
.protect(0..new_pages.bytes().0, sys::Protect::ReadWrite)
.ok()?;
.map_err(|e| e.into())?;
new_memory.as_slice_mut()[..self.current.bytes().0]
.copy_from_slice(&self.memory.as_slice()[..self.current.bytes().0]);
@ -97,7 +101,7 @@ impl DynamicMemory {
let old_pages = self.current;
self.current = new_pages;
Some(old_pages)
Ok(old_pages)
}
pub fn as_slice(&self) -> &[u8] {

View File

@ -1,5 +1,5 @@
use crate::{
error::CreationError,
error::{CreationError, GrowError},
export::Export,
import::IsExport,
memory::dynamic::DYNAMIC_GUARD_SIZE,
@ -89,8 +89,8 @@ impl Memory {
self.desc
}
/// Grow this memory by the specfied number of pages.
pub fn grow(&self, delta: Pages) -> Option<Pages> {
/// Grow this memory by the specified number of pages.
pub fn grow(&self, delta: Pages) -> Result<Pages, GrowError> {
match &self.variant {
MemoryVariant::Unshared(unshared_mem) => unshared_mem.grow(delta),
MemoryVariant::Shared(shared_mem) => shared_mem.grow(delta),
@ -244,7 +244,7 @@ impl UnsharedMemory {
})
}
pub fn grow(&self, delta: Pages) -> Option<Pages> {
pub fn grow(&self, delta: Pages) -> Result<Pages, GrowError> {
let mut storage = self.internal.storage.borrow_mut();
let mut local = self.internal.local.get();
@ -292,7 +292,7 @@ impl SharedMemory {
Ok(Self { desc })
}
pub fn grow(&self, _delta: Pages) -> Option<Pages> {
pub fn grow(&self, _delta: Pages) -> Result<Pages, GrowError> {
unimplemented!()
}

View File

@ -1,3 +1,4 @@
use crate::error::GrowError;
use crate::{
error::CreationError,
memory::static_::{SAFE_STATIC_GUARD_SIZE, SAFE_STATIC_HEAP_SIZE},
@ -61,27 +62,30 @@ impl StaticMemory {
self.current
}
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Option<Pages> {
pub fn grow(&mut self, delta: Pages, local: &mut vm::LocalMemory) -> Result<Pages, GrowError> {
if delta == Pages(0) {
return Some(self.current);
return Ok(self.current);
}
let new_pages = self.current.checked_add(delta)?;
let new_pages = self.current.checked_add(delta).map_err(|e| e.into())?;
if let Some(max) = self.max {
if new_pages > max {
return None;
return Err(GrowError::ExceededMaxPagesForMemory(
new_pages.0 as usize,
max.0 as usize,
));
}
}
unsafe {
let _ = unsafe {
self.memory
.protect(
self.current.bytes().0..new_pages.bytes().0,
sys::Protect::ReadWrite,
)
.ok()?;
}
.map_err(|e| e.into())
}?;
local.bound = new_pages.bytes().0;
@ -89,7 +93,7 @@ impl StaticMemory {
self.current = new_pages;
Some(old_pages)
Ok(old_pages)
}
pub fn as_slice(&self) -> &[u8] {