Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CachedMemory type #1068

Merged
merged 1 commit into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions crates/wasmi/src/engine/executor/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::{module::DEFAULT_MEMORY_INDEX, store::StoreInner, Instance};
use core::ptr::NonNull;

/// Cached default linear memory bytes.
#[derive(Debug, Copy, Clone)]
pub struct CachedMemory {
data: NonNull<[u8]>,
}

impl Default for CachedMemory {
#[inline]
fn default() -> Self {
Self {
data: NonNull::from(&mut []),
}
}
}

impl CachedMemory {
/// Updates the [`CachedMemory`]'s linear memory data pointer.
///
/// # Note
///
/// This needs to be called whenever the cached pointer might have changed.
///
/// The linear memory pointer might change when ...
///
/// - calling a host function
/// - successfully growing the default linear memory
/// - calling functions defined in other instances via imported or indirect calls
/// - returning from functions that changed the currently used instance
#[inline]
pub fn update(&mut self, ctx: &mut StoreInner, instance: &Instance) {
self.data = Self::load_default_memory(ctx, instance);
}

/// Loads the default [`Memory`] of the currently used [`Instance`].
///
/// # Panics
///
/// If the currently used [`Instance`] does not have a default linear memory.
///
/// [`Memory`]: crate::Memory
#[inline]
fn load_default_memory(ctx: &mut StoreInner, instance: &Instance) -> NonNull<[u8]> {
ctx.resolve_instance(instance)
.get_memory(DEFAULT_MEMORY_INDEX)

Check warning on line 47 in crates/wasmi/src/engine/executor/cache.rs

View check run for this annotation

Codecov / codecov/patch

crates/wasmi/src/engine/executor/cache.rs#L47

Added line #L47 was not covered by tests
.map(|memory| ctx.resolve_memory_mut(&memory).data_mut())
.unwrap_or_else(|| &mut [])
.into()
}

/// Returns a shared slice to the bytes of the cached default linear memory.
#[inline]
pub unsafe fn data(&self) -> &[u8] {
unsafe { self.data.as_ref() }

Check warning on line 56 in crates/wasmi/src/engine/executor/cache.rs

View check run for this annotation

Codecov / codecov/patch

crates/wasmi/src/engine/executor/cache.rs#L56

Added line #L56 was not covered by tests
}

/// Returns an exclusive slice to the bytes of the cached default linear memory.
#[inline]
pub unsafe fn data_mut(&mut self) -> &mut [u8] {
unsafe { self.data.as_mut() }

Check warning on line 62 in crates/wasmi/src/engine/executor/cache.rs

View check run for this annotation

Codecov / codecov/patch

crates/wasmi/src/engine/executor/cache.rs#L62

Added line #L62 was not covered by tests
}
}
26 changes: 5 additions & 21 deletions crates/wasmi/src/engine/executor/instrs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use core::ptr::NonNull;

pub use self::call::{dispatch_host_func, ResumableHostError};
use self::return_::ReturnOutcome;
use super::cache::CachedMemory;
use crate::{
core::{TrapCode, UntypedVal},
engine::{
Expand All @@ -26,7 +25,6 @@ use crate::{
store::StoreInner,
Error,
FuncRef,
Instance,
Memory,
Store,
};
Expand Down Expand Up @@ -82,8 +80,8 @@ struct Executor<'engine> {
sp: FrameRegisters,
/// The pointer to the currently executed instruction.
ip: InstructionPtr,
/// The default memory byte buffer.
memory: NonNull<[u8]>,
/// The cached default memory bytes.
memory: CachedMemory,
/// Stores frequently used instance related data.
cache: &'engine mut InstanceCache,
/// The value stack.
Expand Down Expand Up @@ -134,7 +132,7 @@ impl<'engine> Executor<'engine> {
Self {
sp,
ip,
memory: NonNull::from(&mut []),
memory: CachedMemory::default(),
cache,
value_stack,
call_stack,
Expand All @@ -143,20 +141,6 @@ impl<'engine> Executor<'engine> {
}
}

/// Loads the default [`Memory`] of the currently used [`Instance`].
///
/// # Panics
///
/// If the currently used [`Instance`] does not have a default linear memory.
#[inline]
fn load_default_memory(ctx: &mut StoreInner, instance: &Instance) -> NonNull<[u8]> {
ctx.resolve_instance(instance)
.get_memory(DEFAULT_MEMORY_INDEX)
.map(|memory| ctx.resolve_memory_mut(&memory).data_mut())
.unwrap_or_else(|| &mut [])
.into()
}

#[inline]
fn default_memory(&self, ctx: &StoreInner) -> Memory {
let instance = self.cache.instance();
Expand All @@ -170,7 +154,7 @@ impl<'engine> Executor<'engine> {
fn execute<T>(mut self, store: &mut Store<T>) -> Result<(), Error> {
use Instruction as Instr;
let instance = self.cache.instance();
self.memory = Self::load_default_memory(&mut store.inner, instance);
self.memory.update(&mut store.inner, instance);
loop {
match *self.ip.get() {
Instr::Trap(trap_code) => self.execute_trap(trap_code)?,
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmi/src/engine/executor/instrs/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ impl<'engine> Executor<'engine> {
let func_body = func.func_body();
self.prepare_compiled_func_call::<C>(&mut store.inner, results, func_body)?;
self.cache.update_instance(&instance);
self.memory = Self::load_default_memory(&mut store.inner, &instance);
self.memory.update(&mut store.inner, &instance);
Ok(())
}
FuncEntity::Host(host_func) => {
Expand Down Expand Up @@ -513,7 +513,7 @@ impl<'engine> Executor<'engine> {
false => ResumableHostError::new(error, *func, results).into(),
})?;
self.cache.reset_last_global();
self.memory = Self::load_default_memory(&mut store.inner, caller.instance());
self.memory.update(&mut store.inner, caller.instance());
let results = results.iter(len_results);
let returned = self.value_stack.drop_return(max_inout);
for (result, value) in results.zip(returned) {
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/executor/instrs/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl<'engine> Executor<'engine> {
) -> Result<(), Error> {
// Safety: `self.memory` is always re-loaded conservatively whenever
// the heap allocations and thus the pointer might have changed.
let memory = unsafe { self.memory.as_ref() };
let memory = unsafe { self.memory.data() };
let loaded_value = load_extend(memory, address, offset)?;
self.set_register(result, loaded_value);
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/executor/instrs/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl<'engine> Executor<'engine> {
// linear memory so we need to reset it in order for the cache to
// reload in case it is used again.
let instance = self.cache.instance();
self.memory = Self::load_default_memory(store, instance);
self.memory.update(store, instance);
return_value
}
Err(EntityGrowError::InvalidGrow) => EntityGrowError::ERROR_CODE,
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/executor/instrs/return_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl<'engine> Executor<'engine> {
Self::init_call_frame_impl(self.value_stack, &mut self.sp, &mut self.ip, caller);
let instance = caller.instance();
self.cache.update_instance(instance);
self.memory = Self::load_default_memory(store, instance);
self.memory.update(store, instance);
ReturnOutcome::Wasm
}
None => ReturnOutcome::Host,
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmi/src/engine/executor/instrs/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<'engine> Executor<'engine> {
) -> Result<(), Error> {
// Safety: `self.memory` is always re-loaded conservatively whenever
// the heap allocations and thus the pointer might have changed.
let memory = unsafe { self.memory.as_mut() };
let memory = unsafe { self.memory.data_mut() };
store_wrap(memory, address, offset, value)?;
Ok(())
}
Expand Down
1 change: 1 addition & 0 deletions crates/wasmi/src/engine/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::{
#[cfg(doc)]
use crate::engine::StackLimits;

mod cache;
mod instrs;
mod stack;

Expand Down
Loading