merge upstream/master into wasmer-private/feature/llvm-backend

This commit is contained in:
Lachlan Sneff
2019-03-04 13:03:32 -08:00
60 changed files with 1827 additions and 2087 deletions

View File

@ -12,7 +12,7 @@ use crate::{
module::ModuleInfo,
sys::Memory,
};
use std::ptr::NonNull;
use std::{any::Any, ptr::NonNull};
pub mod sys {
pub use crate::sys::*;
@ -79,7 +79,7 @@ pub trait ProtectedCaller: Send + Sync {
}
pub trait UserTrapper {
unsafe fn do_early_trap(&self, msg: String) -> !;
unsafe fn do_early_trap(&self, data: Box<dyn Any>) -> !;
}
pub trait FuncResolver: Send + Sync {

View File

@ -2,8 +2,8 @@ use crate::{
module::{Module, ModuleInfo},
sys::Memory,
};
use sha2::{Digest, Sha256};
use std::{io, mem, slice};
use blake2b_simd::blake2bp;
use std::{fmt, io, mem, slice};
#[derive(Debug)]
pub enum InvalidFileType {
@ -33,7 +33,7 @@ impl From<io::Error> for Error {
///
/// [`Cache`]: trait.Cache.html
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct WasmHash([u8; 32]);
pub struct WasmHash([u8; 32], [u8; 32]);
impl WasmHash {
/// Hash a wasm module.
@ -42,19 +42,31 @@ impl WasmHash {
/// This does no verification that the supplied data
/// is, in fact, a wasm module.
pub fn generate(wasm: &[u8]) -> Self {
let mut array = [0u8; 32];
array.copy_from_slice(Sha256::digest(wasm).as_slice());
WasmHash(array)
let mut first_part = [0u8; 32];
let mut second_part = [0u8; 32];
let mut state = blake2bp::State::new();
state.update(wasm);
let hasher = state.finalize();
let generic_array = hasher.as_bytes();
first_part.copy_from_slice(&generic_array[0..32]);
second_part.copy_from_slice(&generic_array[32..64]);
WasmHash(first_part, second_part)
}
/// Create the hexadecimal representation of the
/// stored hash.
pub fn encode(self) -> String {
hex::encode(self.0)
hex::encode(&self.into_array() as &[u8])
}
pub(crate) fn into_array(self) -> [u8; 32] {
self.0
pub(crate) fn into_array(self) -> [u8; 64] {
let mut total = [0u8; 64];
total[0..32].copy_from_slice(&self.0);
total[32..64].copy_from_slice(&self.1);
total
}
}
@ -189,8 +201,8 @@ impl Artifact {
///
/// The `wasmer-runtime` supplies a naive `FileSystemCache` api.
pub trait Cache {
type LoadError;
type StoreError;
type LoadError: fmt::Debug;
type StoreError: fmt::Debug;
fn load(&self, key: WasmHash) -> Result<Module, Self::LoadError>;
fn store(&mut self, key: WasmHash, module: Module) -> Result<(), Self::StoreError>;

View File

@ -1,8 +1,9 @@
use crate::types::{
FuncSig, GlobalDescriptor, MemoryDescriptor, MemoryIndex, TableDescriptor, TableIndex, Type,
Value,
};
use core::borrow::Borrow;
use std::sync::Arc;
use std::{any::Any, sync::Arc};
pub type Result<T> = std::result::Result<T, Error>;
pub type CompileResult<T> = std::result::Result<T, CompileError>;
@ -120,28 +121,11 @@ impl std::error::Error for LinkError {}
/// The main way to do this is `Instance.call`.
///
/// Comparing two `RuntimeError`s always evaluates to false.
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum RuntimeError {
OutOfBoundsAccess {
memory: MemoryIndex,
addr: Option<u32>,
},
TableOutOfBounds {
table: TableIndex,
},
IndirectCallSignature {
table: TableIndex,
},
IndirectCallToNull {
table: TableIndex,
},
IllegalArithmeticOperation,
User {
msg: String,
},
Unknown {
msg: String,
},
Trap { msg: Box<str> },
Exception { data: Box<[Value]> },
Panic { data: Box<dyn Any> },
}
impl PartialEq for RuntimeError {
@ -153,30 +137,13 @@ impl PartialEq for RuntimeError {
impl std::fmt::Display for RuntimeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
RuntimeError::IndirectCallSignature { table } => write!(
f,
"Indirect call signature error with Table Index \"{:?}\"",
table
),
RuntimeError::IndirectCallToNull { table } => {
write!(f, "Indirect call to null with table index \"{:?}\"", table)
RuntimeError::Trap { ref msg } => {
write!(f, "WebAssembly trap occured during runtime: {}", msg)
}
RuntimeError::IllegalArithmeticOperation => write!(f, "Illegal arithmetic operation"),
RuntimeError::OutOfBoundsAccess { memory, addr } => match addr {
Some(addr) => write!(
f,
"Out-of-bounds access with memory index {:?} and address {}",
memory, addr
),
None => write!(f, "Out-of-bounds access with memory index {:?}", memory),
},
RuntimeError::TableOutOfBounds { table } => {
write!(f, "Table out of bounds with table index \"{:?}\"", table)
RuntimeError::Exception { ref data } => {
write!(f, "Uncaught WebAssembly exception: {:?}", data)
}
RuntimeError::Unknown { msg } => {
write!(f, "Unknown runtime error with message: \"{}\"", msg)
}
RuntimeError::User { msg } => write!(f, "User runtime error with message: \"{}\"", msg),
RuntimeError::Panic { data: _ } => write!(f, "User-defined \"panic\""),
}
}
}
@ -232,7 +199,7 @@ impl std::error::Error for ResolveError {}
/// be the `CallError::Runtime(RuntimeError)` variant.
///
/// Comparing two `CallError`s always evaluates to false.
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum CallError {
Resolve(ResolveError),
Runtime(RuntimeError),
@ -291,7 +258,7 @@ impl std::error::Error for CreationError {}
/// of a webassembly module.
///
/// Comparing two `Error`s always evaluates to false.
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum Error {
CompileError(CompileError),
LinkError(Vec<LinkError>),
@ -357,8 +324,127 @@ impl From<ResolveError> for CallError {
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self)
match self {
Error::CompileError(err) => write!(f, "compile error: {}", err),
Error::LinkError(errs) => {
if errs.len() == 1 {
write!(f, "link error: {}", errs[0])
} else {
write!(f, "{} link errors:", errs.len())?;
for (i, err) in errs.iter().enumerate() {
write!(f, " ({} of {}) {}", i + 1, errs.len(), err)?;
}
Ok(())
}
}
Error::RuntimeError(err) => write!(f, "runtime error: {}", err),
Error::ResolveError(err) => write!(f, "resolve error: {}", err),
Error::CallError(err) => write!(f, "call error: {}", err),
Error::CreationError(err) => write!(f, "creation error: {}", err),
}
}
}
impl std::error::Error for Error {}
#[derive(Debug)]
pub enum GrowError {
MemoryGrowError,
TableGrowError,
ExceededMaxPages(PageError),
ExceededMaxPagesForMemory(usize, usize),
CouldNotProtectMemory(MemoryProtectionError),
CouldNotCreateMemory(MemoryCreationError),
}
impl std::fmt::Display for GrowError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
GrowError::MemoryGrowError => write!(f, "Unable to grow memory"),
GrowError::TableGrowError => write!(f, "Unable to grow table"),
GrowError::ExceededMaxPages(e) => write!(f, "Grow Error: {}", e),
GrowError::ExceededMaxPagesForMemory(left, added) => write!(f, "Failed to add pages because would exceed maximum number of pages for the memory. Left: {}, Added: {}", left, added),
GrowError::CouldNotCreateMemory(e) => write!(f, "Grow Error: {}", e),
GrowError::CouldNotProtectMemory(e) => write!(f, "Grow Error: {}", e),
}
}
}
impl std::error::Error for GrowError {}
#[derive(Debug)]
pub enum PageError {
// left, right, added
ExceededMaxPages(usize, usize, usize),
}
impl std::fmt::Display for PageError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
PageError::ExceededMaxPages(left, right, added) => write!(f, "Failed to add pages because would exceed maximum number of pages. Left: {}, Right: {}, Pages added: {}", left, right, added),
}
}
}
impl std::error::Error for PageError {}
impl Into<GrowError> for PageError {
fn into(self) -> GrowError {
GrowError::ExceededMaxPages(self)
}
}
#[derive(Debug)]
pub enum MemoryCreationError {
VirtualMemoryAllocationFailed(usize, String),
CouldNotCreateMemoryFromFile(std::io::Error),
}
impl std::fmt::Display for MemoryCreationError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
MemoryCreationError::VirtualMemoryAllocationFailed(size, msg) => write!(
f,
"Allocation virtual memory with size {} failed. \nErrno message: {}",
size, msg
),
MemoryCreationError::CouldNotCreateMemoryFromFile(e) => write!(f, "IO Error: {}", e),
}
}
}
impl std::error::Error for MemoryCreationError {}
impl Into<GrowError> for MemoryCreationError {
fn into(self) -> GrowError {
GrowError::CouldNotCreateMemory(self)
}
}
impl From<std::io::Error> for MemoryCreationError {
fn from(io_error: std::io::Error) -> Self {
MemoryCreationError::CouldNotCreateMemoryFromFile(io_error)
}
}
#[derive(Debug)]
pub enum MemoryProtectionError {
ProtectionFailed(usize, usize, String),
}
impl std::fmt::Display for MemoryProtectionError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
MemoryProtectionError::ProtectionFailed(start, size, msg) => write!(
f,
"Allocation virtual memory starting at {} with size {} failed. \nErrno message: {}",
start, size, msg
),
}
}
}
impl std::error::Error for MemoryProtectionError {}
impl Into<GrowError> for MemoryProtectionError {
fn into(self) -> GrowError {
GrowError::CouldNotProtectMemory(self)
}
}

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] {

View File

@ -1,6 +1,6 @@
use crate::{
backend::{Backend, FuncResolver, ProtectedCaller},
cache::{Artifact, Error as CacheError, WasmHash},
cache::{Artifact, Error as CacheError},
error,
import::ImportObject,
structures::{Map, TypedIndex},

View File

@ -56,6 +56,10 @@ where
pub fn into_boxed_map(self) -> BoxedMap<K, V> {
BoxedMap::new(self.elems.into_boxed_slice())
}
pub fn into_vec(self) -> Vec<V> {
self.elems
}
}
impl<K, V> Map<K, V>

View File

@ -1,3 +1,5 @@
use crate::error::MemoryCreationError;
use crate::error::MemoryProtectionError;
use errno;
use nix::libc;
use page_size;
@ -16,13 +18,13 @@ pub struct Memory {
}
impl Memory {
pub fn from_file_path<P>(path: P, protection: Protect) -> Result<Self, String>
pub fn from_file_path<P>(path: P, protection: Protect) -> Result<Self, MemoryCreationError>
where
P: AsRef<Path>,
{
let file = File::open(path).map_err(|e| e.to_string())?;
let file = File::open(path)?;
let file_len = file.metadata().map_err(|e| e.to_string())?.len();
let file_len = file.metadata()?.len();
let raw_fd = RawFd::from_file(file);
@ -38,7 +40,10 @@ impl Memory {
};
if ptr == -1 as _ {
Err(errno::errno().to_string())
Err(MemoryCreationError::VirtualMemoryAllocationFailed(
file_len as usize,
errno::errno().to_string(),
))
} else {
Ok(Self {
ptr: ptr as *mut u8,
@ -84,7 +89,7 @@ impl Memory {
}
}
pub fn with_size(size: usize) -> Result<Self, String> {
pub fn with_size(size: usize) -> Result<Self, MemoryCreationError> {
if size == 0 {
return Ok(Self {
ptr: ptr::null_mut(),
@ -108,7 +113,10 @@ impl Memory {
};
if ptr == -1 as _ {
Err(errno::errno().to_string())
Err(MemoryCreationError::VirtualMemoryAllocationFailed(
size,
errno::errno().to_string(),
))
} else {
Ok(Self {
ptr: ptr as *mut u8,
@ -123,7 +131,7 @@ impl Memory {
&mut self,
range: impl RangeBounds<usize>,
protection: Protect,
) -> Result<(), String> {
) -> Result<(), MemoryProtectionError> {
let protect = protection.to_protect_const();
let range_start = match range.start_bound() {
@ -147,7 +155,11 @@ impl Memory {
let success = libc::mprotect(start as _, size, protect as i32);
if success == -1 {
Err(errno::errno().to_string())
Err(MemoryProtectionError::ProtectionFailed(
start as usize,
size,
errno::errno().to_string(),
))
} else {
self.protection = protection;
Ok(())

View File

@ -1,3 +1,5 @@
use crate::error::MemoryCreationError;
use crate::error::MemoryProtectionError;
use page_size;
use std::ops::{Bound, RangeBounds};
use std::{ptr, slice};
@ -44,7 +46,7 @@ impl Memory {
}
}
pub fn with_size(size: usize) -> Result<Self, String> {
pub fn with_size(size: usize) -> Result<Self, MemoryCreationError> {
if size == 0 {
return Ok(Self {
ptr: ptr::null_mut(),
@ -58,7 +60,10 @@ impl Memory {
let ptr = unsafe { VirtualAlloc(ptr::null_mut(), size, MEM_RESERVE, PAGE_NOACCESS) };
if ptr.is_null() {
Err("unable to allocate memory".to_string())
Err(MemoryCreationError::VirtualMemoryAllocationFailed(
size,
"unable to allocate memory".to_string(),
))
} else {
Ok(Self {
ptr: ptr as *mut u8,
@ -72,7 +77,7 @@ impl Memory {
&mut self,
range: impl RangeBounds<usize>,
protect: Protect,
) -> Result<(), String> {
) -> Result<(), MemoryProtectionError> {
let protect_const = protect.to_protect_const();
let range_start = match range.start_bound() {
@ -98,7 +103,11 @@ impl Memory {
let ptr = VirtualAlloc(start as _, size, MEM_COMMIT, protect_const);
if ptr.is_null() {
Err("unable to protect memory".to_string())
Err(MemoryProtectionError::ProtectionFailed(
start as usize,
size,
"unable to protect memory".to_string(),
))
} else {
self.protection = protect;
Ok(())

View File

@ -11,6 +11,7 @@ mod anyfunc;
pub use self::anyfunc::Anyfunc;
use self::anyfunc::AnyfuncTable;
use crate::error::GrowError;
pub enum Element<'a> {
Anyfunc(Anyfunc<'a>),
@ -108,15 +109,15 @@ impl Table {
}
/// Grow this table by `delta`.
pub fn grow(&self, delta: u32) -> Option<u32> {
pub fn grow(&self, delta: u32) -> Result<u32, GrowError> {
if delta == 0 {
return Some(self.size());
return Ok(self.size());
}
match &mut *self.storage.borrow_mut() {
(TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => {
anyfunc_table.grow(delta, local)
}
(TableStorage::Anyfunc(ref mut anyfunc_table), ref mut local) => anyfunc_table
.grow(delta, local)
.ok_or(GrowError::TableGrowError),
}
}

View File

@ -6,7 +6,7 @@ use crate::{
types::{FuncSig, Type, WasmExternType},
vm::Ctx,
};
use std::{cell::UnsafeCell, fmt, marker::PhantomData, mem, panic, ptr, sync::Arc};
use std::{any::Any, cell::UnsafeCell, fmt, marker::PhantomData, mem, panic, ptr, sync::Arc};
thread_local! {
pub static EARLY_TRAPPER: UnsafeCell<Option<Box<dyn UserTrapper>>> = UnsafeCell::new(None);
@ -40,14 +40,14 @@ pub trait TrapEarly<Rets>
where
Rets: WasmTypeList,
{
fn report(self) -> Result<Rets, String>;
fn report(self) -> Result<Rets, Box<dyn Any>>;
}
impl<Rets> TrapEarly<Rets> for Rets
where
Rets: WasmTypeList,
{
fn report(self) -> Result<Rets, String> {
fn report(self) -> Result<Rets, Box<dyn Any>> {
Ok(self)
}
}
@ -55,10 +55,10 @@ where
impl<Rets, E> TrapEarly<Rets> for Result<Rets, E>
where
Rets: WasmTypeList,
E: fmt::Debug,
E: Any,
{
fn report(self) -> Result<Rets, String> {
self.map_err(|err| format!("Error: {:?}", err))
fn report(self) -> Result<Rets, Box<dyn Any>> {
self.map_err(|err| Box::new(err) as Box<dyn Any>)
}
}
@ -191,25 +191,17 @@ macro_rules! impl_traits {
extern fn wrap<$( $x: WasmExternType, )* Rets: WasmTypeList, Trap: TrapEarly<Rets>, FN: Fn( &mut Ctx $( ,$x )* ) -> Trap>( ctx: &mut Ctx $( ,$x: $x )* ) -> Rets::CStruct {
let f: FN = unsafe { mem::transmute_copy(&()) };
let msg = match panic::catch_unwind(panic::AssertUnwindSafe(|| {
let err = match panic::catch_unwind(panic::AssertUnwindSafe(|| {
f( ctx $( ,$x )* ).report()
})) {
Ok(Ok(returns)) => return returns.into_c_struct(),
Ok(Err(err)) => err,
Err(err) => {
if let Some(s) = err.downcast_ref::<&str>() {
s.to_string()
} else if let Some(s) = err.downcast_ref::<String>() {
s.clone()
} else {
"a panic occurred, but no additional information is available".to_string()
}
},
Err(err) => err,
};
unsafe {
if let Some(early_trapper) = &*EARLY_TRAPPER.with(|ucell| ucell.get()) {
early_trapper.do_early_trap(msg)
early_trapper.do_early_trap(err)
} else {
eprintln!("panic handling not setup");
std::process::exit(1)

View File

@ -1,3 +1,4 @@
use crate::error::PageError;
use std::{
fmt,
ops::{Add, Sub},
@ -11,12 +12,16 @@ const WASM_MAX_PAGES: usize = 65_536;
pub struct Pages(pub u32);
impl Pages {
pub fn checked_add(self, rhs: Pages) -> Option<Pages> {
pub fn checked_add(self, rhs: Pages) -> Result<Pages, PageError> {
let added = (self.0 as usize) + (rhs.0 as usize);
if added <= WASM_MAX_PAGES {
Some(Pages(added as u32))
Ok(Pages(added as u32))
} else {
None
Err(PageError::ExceededMaxPages(
self.0 as usize,
rhs.0 as usize,
added,
))
}
}

View File

@ -20,10 +20,9 @@ pub unsafe extern "C" fn local_static_memory_grow(
let local_memory = *ctx.memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut StaticMemory;
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
old.0 as i32
} else {
-1
match (*memory).grow(delta, &mut *local_memory) {
Ok(old) => old.0 as i32,
Err(_) => -1,
}
}
@ -45,10 +44,9 @@ pub unsafe extern "C" fn local_dynamic_memory_grow(
let local_memory = *ctx.memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut DynamicMemory;
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
old.0 as i32
} else {
-1
match (*memory).grow(delta, &mut *local_memory) {
Ok(old) => old.0 as i32,
Err(_) => -1,
}
}
@ -74,10 +72,9 @@ pub unsafe extern "C" fn imported_static_memory_grow(
let local_memory = *ctx.imported_memories.add(import_memory_index.index());
let memory = (*local_memory).memory as *mut StaticMemory;
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
old.0 as i32
} else {
-1
match (*memory).grow(delta, &mut *local_memory) {
Ok(old) => old.0 as i32,
Err(_) => -1,
}
}
@ -99,10 +96,9 @@ pub unsafe extern "C" fn imported_dynamic_memory_grow(
let local_memory = *ctx.imported_memories.add(memory_index.index());
let memory = (*local_memory).memory as *mut DynamicMemory;
if let Some(old) = (*memory).grow(delta, &mut *local_memory) {
old.0 as i32
} else {
-1
match (*memory).grow(delta, &mut *local_memory) {
Ok(old) => old.0 as i32,
Err(_) => -1,
}
}