Skip to content

Commit

Permalink
Improve Memory API (#1082)
Browse files Browse the repository at this point in the history
* add Memory::size API

* change return type of Memory::grow to u32

* use u32 instead of Pages parameter in Memory::grow

* add Memory::{data_ptr, data_size} methods

* remove Memory::current_pages private method
  • Loading branch information
Robbepop authored Jun 24, 2024
1 parent d088395 commit f1f92e4
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 39 deletions.
8 changes: 4 additions & 4 deletions crates/wasmi/benches/benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::{
sync::OnceLock,
};
use wasmi::{
core::{Pages, TrapCode, ValType, F32, F64},
core::{TrapCode, ValType, F32, F64},
CompilationMode,
Engine,
Extern,
Expand Down Expand Up @@ -1328,7 +1328,7 @@ fn bench_execute_memory_sum(c: &mut Criterion) {
.get_export(&store, "mem")
.and_then(Extern::into_memory)
.unwrap();
mem.grow(&mut store, Pages::new(1).unwrap()).unwrap();
mem.grow(&mut store, 1).unwrap();
let len = 100_000;
let mut expected_sum: i64 = 0;
for (n, byte) in &mut mem.data_mut(&mut store)[..len].iter_mut().enumerate() {
Expand Down Expand Up @@ -1360,7 +1360,7 @@ fn bench_execute_memory_fill(c: &mut Criterion) {
.get_export(&store, "mem")
.and_then(Extern::into_memory)
.unwrap();
mem.grow(&mut store, Pages::new(1).unwrap()).unwrap();
mem.grow(&mut store, 1).unwrap();
let ptr = 0x100;
let len = 100_000;
let value = 0x42_u8;
Expand Down Expand Up @@ -1470,7 +1470,7 @@ fn bench_execute_vec_add(c: &mut Criterion) {
.get_export(&store, "mem")
.and_then(Extern::into_memory)
.unwrap();
mem.grow(&mut store, Pages::new(25).unwrap()).unwrap();
mem.grow(&mut store, 1).unwrap();
let len = 100_000;
test_for(
b,
Expand Down
15 changes: 3 additions & 12 deletions crates/wasmi/src/engine/executor/instrs/memory.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use crate::{core::Pages, store::StoreInner, Store};

use super::Executor;
use crate::{
core::TrapCode,
Expand All @@ -8,8 +6,9 @@ use crate::{
code_map::InstructionPtr,
},
error::EntityGrowError,
store::ResourceLimiterRef,
store::{ResourceLimiterRef, StoreInner},
Error,
Store,
};

impl<'engine> Executor<'engine> {
Expand All @@ -35,7 +34,7 @@ impl<'engine> Executor<'engine> {
#[inline(always)]
pub fn execute_memory_size(&mut self, store: &StoreInner, result: Register) {
let memory = self.get_default_memory();
let size: u32 = store.resolve_memory(&memory).current_pages().into();
let size = store.resolve_memory(&memory).size();
self.set_register(result, size);
self.next_instr()
}
Expand Down Expand Up @@ -79,14 +78,6 @@ impl<'engine> Executor<'engine> {
self.execute_memory_size(store, result);
return Ok(());
}
let delta = match Pages::new(delta) {
Some(pages) => pages,
None => {
// Cannot grow memory so we push the expected error value.
self.set_register(result, EntityGrowError::ERROR_CODE);
return self.try_next_instr();
}
};
let memory = self.get_default_memory();
let (memory, fuel) = store.resolve_memory_and_fuel_mut(&memory);
let return_value = memory
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmi/src/memory/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ use std::{slice, vec, vec::Vec};
#[derive(Debug)]
pub struct ByteBuffer {
/// The pointer to the underlying byte buffer.
ptr: *mut u8,
pub(super) ptr: *mut u8,
/// The current length of the byte buffer.
///
/// # Note
///
/// - **Vec:** `vec.len()`
/// - **Static:** The accessible subslice of the entire underlying static byte buffer.
len: usize,
pub(super) len: usize,
/// The capacity of the current allocation.
///
/// # Note
Expand Down
77 changes: 56 additions & 21 deletions crates/wasmi/src/memory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,15 @@ impl MemoryEntity {
}

/// Returns the amount of pages in use by the linear memory.
pub fn current_pages(&self) -> Pages {
fn current_pages(&self) -> Pages {
self.current_pages
}

/// Returns the size, in WebAssembly pages, of this Wasm linear memory.
pub fn size(&self) -> u32 {
self.current_pages.into()
}

/// Grows the linear memory by the given amount of new pages.
///
/// Returns the amount of pages before the operation upon success.
Expand All @@ -237,26 +242,28 @@ impl MemoryEntity {
/// the grow operation.
pub fn grow(
&mut self,
additional: Pages,
additional: u32,
fuel: Option<&mut Fuel>,
limiter: &mut ResourceLimiterRef<'_>,
) -> Result<Pages, EntityGrowError> {
) -> Result<u32, EntityGrowError> {
fn notify_limiter(
limiter: &mut ResourceLimiterRef<'_>,
err: EntityGrowError,
) -> Result<Pages, EntityGrowError> {
) -> Result<u32, EntityGrowError> {
if let Some(limiter) = limiter.as_resource_limiter() {
limiter.memory_grow_failed(&MemoryError::OutOfBoundsGrowth)
}
Err(err)
}

let current_pages = self.current_pages();
if additional == Pages::from(0) {
// Nothing to do in this case. Bail out early.
return Ok(current_pages);
if additional == 0 {
return Ok(self.size());
}
let Some(additional) = Pages::new(additional) else {
return Err(EntityGrowError::InvalidGrow);
};

let current_pages = self.current_pages();
let maximum_pages = self.ty().maximum_pages().unwrap_or_else(Pages::max);
let desired_pages = current_pages.checked_add(additional);

Expand Down Expand Up @@ -300,7 +307,7 @@ impl MemoryEntity {
// 3. There is enough fuel for the operation.
self.bytes.grow(new_size);
self.current_pages = new_pages;
Ok(current_pages)
Ok(u32::from(current_pages))
}

/// Returns a shared slice to the bytes underlying to the byte buffer.
Expand All @@ -313,6 +320,18 @@ impl MemoryEntity {
self.bytes.data_mut()
}

/// Returns the base pointer, in the host’s address space, that the [`Memory`] is located at.
pub fn data_ptr(&self) -> *mut u8 {
self.bytes.ptr
}

/// Returns the byte length of this [`Memory`].
///
/// The returned value will be a multiple of the wasm page size, 64k.
pub fn data_size(&self) -> usize {
self.bytes.len
}

/// Reads `n` bytes from `memory[offset..offset+n]` into `buffer`
/// where `n` is the length of `buffer`.
///
Expand Down Expand Up @@ -426,17 +445,13 @@ impl Memory {
.dynamic_ty()
}

/// Returns the amount of pages in use by the linear memory.
/// Returns the size, in WebAssembly pages, of this Wasm linear memory.
///
/// # Panics
///
/// Panics if `ctx` does not own this [`Memory`].
pub fn current_pages(&self, ctx: impl AsContext) -> Pages {
ctx.as_context()
.store
.inner
.resolve_memory(self)
.current_pages()
pub fn size(&self, ctx: impl AsContext) -> u32 {
ctx.as_context().store.inner.resolve_memory(self).size()
}

/// Grows the linear memory by the given amount of new pages.
Expand All @@ -451,11 +466,7 @@ impl Memory {
/// # Panics
///
/// Panics if `ctx` does not own this [`Memory`].
pub fn grow(
&self,
mut ctx: impl AsContextMut,
additional: Pages,
) -> Result<Pages, MemoryError> {
pub fn grow(&self, mut ctx: impl AsContextMut, additional: u32) -> Result<u32, MemoryError> {
let (inner, mut limiter) = ctx
.as_context_mut()
.store
Expand Down Expand Up @@ -498,6 +509,30 @@ impl Memory {
(memory.data_mut(), store)
}

/// Returns the base pointer, in the host’s address space, that the [`Memory`] is located at.
///
/// # Panics
///
/// Panics if `ctx` does not own this [`Memory`].
pub fn data_ptr(&self, ctx: impl AsContext) -> *mut u8 {
ctx.as_context().store.inner.resolve_memory(self).data_ptr()
}

/// Returns the byte length of this [`Memory`].
///
/// The returned value will be a multiple of the wasm page size, 64k.
///
/// # Panics
///
/// Panics if `ctx` does not own this [`Memory`].
pub fn data_size(&self, ctx: impl AsContext) -> usize {
ctx.as_context()
.store
.inner
.resolve_memory(self)
.data_size()
}

/// Reads `n` bytes from `memory[offset..offset+n]` into `buffer`
/// where `n` is the length of `buffer`.
///
Expand Down

0 comments on commit f1f92e4

Please sign in to comment.