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

Refactor the internals of vm::Memory to simplify the RuntimeLinearMemory trait #9577

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion crates/c-api/include/wasmtime/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ WASMTIME_CONFIG_PROP(void, macos_use_mach_ports, bool)
* https://docs.wasmtime.dev/api/wasmtime/trait.LinearMemory.html
*/
typedef uint8_t *(*wasmtime_memory_get_callback_t)(void *env, size_t *byte_size,
size_t *maximum_byte_size);
size_t *byte_capacity);

/**
* Grow the memory to the `new_size` in bytes.
Expand Down
31 changes: 8 additions & 23 deletions crates/c-api/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#![cfg_attr(not(feature = "cache"), allow(unused_imports))]

use crate::{handle_result, wasm_memorytype_t, wasmtime_error_t};
use std::ops::Range;
use std::os::raw::c_char;
use std::ptr;
use std::{ffi::CStr, sync::Arc};
Expand Down Expand Up @@ -322,37 +321,23 @@ struct CHostLinearMemory {
unsafe impl LinearMemory for CHostLinearMemory {
fn byte_size(&self) -> usize {
let mut byte_size = 0;
let mut maximum_byte_size = 0;
let mut byte_capacity = 0;
let cb = self.get_memory;
cb(self.foreign.data, &mut byte_size, &mut maximum_byte_size);
cb(self.foreign.data, &mut byte_size, &mut byte_capacity);
return byte_size;
}
fn maximum_byte_size(&self) -> Option<usize> {
fn byte_capacity(&self) -> usize {
let mut byte_size = 0;
let mut maximum_byte_size = 0;
let mut byte_capacity = 0;
let cb = self.get_memory;
cb(self.foreign.data, &mut byte_size, &mut maximum_byte_size);
if maximum_byte_size == 0 {
None
} else {
Some(maximum_byte_size)
}
cb(self.foreign.data, &mut byte_size, &mut byte_capacity);
byte_capacity
}
fn as_ptr(&self) -> *mut u8 {
let mut byte_size = 0;
let mut maximum_byte_size = 0;
let cb = self.get_memory;
cb(self.foreign.data, &mut byte_size, &mut maximum_byte_size)
}
fn wasm_accessible(&self) -> Range<usize> {
let mut byte_size = 0;
let mut maximum_byte_size = 0;
let mut byte_capacity = 0;
let cb = self.get_memory;
let ptr = cb(self.foreign.data, &mut byte_size, &mut maximum_byte_size);
Range {
start: ptr as usize,
end: ptr as usize + byte_size,
}
cb(self.foreign.data, &mut byte_size, &mut byte_capacity)
}
fn grow_to(&mut self, new_size: usize) -> Result<()> {
let cb = self.grow_memory;
Expand Down
15 changes: 3 additions & 12 deletions crates/fuzzing/src/generators/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use anyhow::Result;
use arbitrary::{Arbitrary, Unstructured};
use std::ops::Range;
use wasmtime::{LinearMemory, MemoryCreator, MemoryType};

/// A description of a memory config, image, etc... that can be used to test
Expand Down Expand Up @@ -232,7 +231,6 @@ pub struct UnalignedMemory {
/// This memory is always one byte larger than the actual size of linear
/// memory.
src: Vec<u8>,
maximum: Option<usize>,
}

unsafe impl LinearMemory for UnalignedMemory {
Expand All @@ -242,8 +240,8 @@ unsafe impl LinearMemory for UnalignedMemory {
self.src.len() - 1
}

fn maximum_byte_size(&self) -> Option<usize> {
self.maximum
fn byte_capacity(&self) -> usize {
self.src.capacity() - 1
}

fn grow_to(&mut self, new_size: usize) -> Result<()> {
Expand All @@ -257,12 +255,6 @@ unsafe impl LinearMemory for UnalignedMemory {
// of memory is always unaligned.
self.src[1..].as_ptr() as *mut _
}

fn wasm_accessible(&self) -> Range<usize> {
let base = self.as_ptr() as usize;
let len = self.byte_size();
base..base + len
}
}

/// A mechanism to generate [`UnalignedMemory`] at runtime.
Expand All @@ -273,15 +265,14 @@ unsafe impl MemoryCreator for UnalignedMemoryCreator {
&self,
_ty: MemoryType,
minimum: usize,
maximum: Option<usize>,
_maximum: Option<usize>,
reserved_size_in_bytes: Option<usize>,
guard_size_in_bytes: usize,
) -> Result<Box<dyn LinearMemory>, String> {
assert_eq!(guard_size_in_bytes, 0);
assert!(reserved_size_in_bytes.is_none() || reserved_size_in_bytes == Some(0));
Ok(Box::new(UnalignedMemory {
src: vec![0; minimum + 1],
maximum,
}))
}
}
15 changes: 5 additions & 10 deletions crates/wasmtime/src/runtime/memory.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use crate::prelude::*;
use crate::runtime::vm::{RuntimeLinearMemory, VMMemoryImport};
use crate::runtime::vm::VMMemoryImport;
use crate::store::{StoreData, StoreOpaque, Stored};
use crate::trampoline::generate_memory_export;
use crate::Trap;
use crate::{AsContext, AsContextMut, Engine, MemoryType, StoreContext, StoreContextMut};
use core::cell::UnsafeCell;
use core::fmt;
use core::ops::Range;
use core::slice;
use core::time::Duration;

Expand Down Expand Up @@ -676,11 +675,11 @@ pub unsafe trait LinearMemory: Send + Sync + 'static {
/// Returns the number of allocated bytes which are accessible at this time.
fn byte_size(&self) -> usize;

/// Returns the maximum number of bytes the memory can grow to.
/// Returns byte capacity of this linear memory's current allocation.
///
/// Returns `None` if the memory is unbounded, or `Some` if memory cannot
/// grow beyond a specified limit.
fn maximum_byte_size(&self) -> Option<usize>;
/// Growth up to this value should not relocate the linear memory base
/// pointer.
fn byte_capacity(&self) -> usize;

/// Grows this memory to have the `new_size`, in bytes, specified.
///
Expand All @@ -691,10 +690,6 @@ pub unsafe trait LinearMemory: Send + Sync + 'static {

/// Return the allocated memory as a mutable pointer to u8.
fn as_ptr(&self) -> *mut u8;

/// Returns the range of native addresses that WebAssembly can natively
/// access from this linear memory, including guard pages.
fn wasm_accessible(&self) -> Range<usize>;
}

/// A memory creator. Can be used to provide a memory creator
Expand Down
48 changes: 7 additions & 41 deletions crates/wasmtime/src/runtime/trampoline/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ use crate::prelude::*;
use crate::runtime::vm::mpk::ProtectionKey;
use crate::runtime::vm::{
CompiledModuleId, GcHeapAllocationIndex, Imports, InstanceAllocationRequest, InstanceAllocator,
InstanceAllocatorImpl, Memory, MemoryAllocationIndex, MemoryImage, ModuleRuntimeInfo,
InstanceAllocatorImpl, Memory, MemoryAllocationIndex, ModuleRuntimeInfo,
OnDemandInstanceAllocator, RuntimeLinearMemory, RuntimeMemoryCreator, SharedMemory, StorePtr,
Table, TableAllocationIndex, VMMemoryDefinition,
Table, TableAllocationIndex,
};
use crate::store::{InstanceId, StoreOpaque};
use crate::MemoryType;
use alloc::sync::Arc;
use core::ops::Range;
use wasmtime_environ::{
DefinedMemoryIndex, DefinedTableIndex, EntityIndex, HostPtr, MemoryStyle, Module, Tunables,
VMOffsets,
Expand Down Expand Up @@ -76,50 +75,23 @@ pub fn create_memory(

struct LinearMemoryProxy {
mem: Box<dyn LinearMemory>,
page_size_log2: u8,
}

impl RuntimeLinearMemory for LinearMemoryProxy {
fn page_size_log2(&self) -> u8 {
self.page_size_log2
}

fn byte_size(&self) -> usize {
self.mem.byte_size()
}

fn maximum_byte_size(&self) -> Option<usize> {
self.mem.maximum_byte_size()
fn byte_capacity(&self) -> usize {
self.mem.byte_capacity()
}

fn grow_to(&mut self, new_size: usize) -> Result<()> {
self.mem.grow_to(new_size)
}

fn vmmemory(&mut self) -> VMMemoryDefinition {
VMMemoryDefinition {
base: self.mem.as_ptr(),
current_length: self.mem.byte_size().into(),
}
}

fn needs_init(&self) -> bool {
true
}

fn as_any_mut(&mut self) -> &mut dyn core::any::Any {
self
}

fn wasm_accessible(&self) -> Range<usize> {
self.mem.wasm_accessible()
}

fn memory_may_move(&self) -> bool {
// FIXME(#9568): should propagate this up to the `LinearMemory` trait,
// but for now pessimistically assume that consumers might move linear
// memory.
true
fn base_ptr(&self) -> *mut u8 {
self.mem.as_ptr()
}
}

Expand All @@ -133,7 +105,6 @@ impl RuntimeMemoryCreator for MemoryCreatorProxy {
tunables: &Tunables,
minimum: usize,
maximum: Option<usize>,
_: Option<&Arc<MemoryImage>>,
) -> Result<Box<dyn RuntimeLinearMemory>> {
let style = MemoryStyle::for_memory(*ty, tunables);
let reserved_size_in_bytes = match style {
Expand All @@ -150,12 +121,7 @@ impl RuntimeMemoryCreator for MemoryCreatorProxy {
reserved_size_in_bytes,
usize::try_from(tunables.memory_guard_size).unwrap(),
)
.map(|mem| {
Box::new(LinearMemoryProxy {
mem,
page_size_log2: ty.page_size_log2,
}) as Box<dyn RuntimeLinearMemory>
})
.map(|mem| Box::new(LinearMemoryProxy { mem }) as Box<dyn RuntimeLinearMemory>)
.map_err(|e| anyhow!(e))
}
}
Expand Down
16 changes: 0 additions & 16 deletions crates/wasmtime/src/runtime/vm/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,22 +348,6 @@ impl MemoryImageSlot {
}
}

#[cfg(feature = "pooling-allocator")]
pub(crate) fn dummy() -> MemoryImageSlot {
MemoryImageSlot {
// This pointer isn't ever actually used so its value doesn't
// matter but we need to satisfy `NonNull` requirement so create a
// `dangling` pointer as a sentinel that should cause problems if
// it's actually used.
base: NonNull::dangling().into(),
static_size: 0,
image: None,
accessible: 0,
dirty: false,
clear_on_drop: false,
}
}

/// Inform the MemoryImageSlot that it should *not* clear the underlying
/// address space when dropped. This should be used only when the
/// caller will clear or reuse the address space in some other
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use crate::{prelude::*, vm::round_usize_up_to_host_pages};
use std::ffi::c_void;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Mutex;
use wasmtime_environ::{DefinedMemoryIndex, MemoryStyle, Module, Tunables};
use wasmtime_environ::{DefinedMemoryIndex, Module, Tunables};

/// A set of allocator slots.
///
Expand Down Expand Up @@ -338,16 +338,10 @@ impl MemoryPool {
// satisfied by the configuration of this pooling allocator. This
// should be returned as an error through `validate_memory_plans`
// but double-check here to be sure.
let style = MemoryStyle::for_memory(*ty, tunables);
match style {
MemoryStyle::Static { byte_reservation } => {
assert!(
byte_reservation
<= u64::try_from(self.layout.bytes_to_next_stripe_slot()).unwrap()
);
}
MemoryStyle::Dynamic { .. } => {}
}
assert!(
tunables.memory_reservation + tunables.memory_guard_size
<= u64::try_from(self.layout.bytes_to_next_stripe_slot()).unwrap()
);

let base_ptr = self.get_base(allocation_index);
let base_capacity = self.layout.max_memory_bytes;
Expand All @@ -374,14 +368,9 @@ impl MemoryPool {
let initial_size = usize::try_from(initial_size).unwrap();
slot.instantiate(initial_size, image, ty, tunables)?;

Memory::new_static(
ty,
base_ptr,
base_capacity,
slot,
self.layout.bytes_to_next_stripe_slot(),
unsafe { &mut *request.store.get().unwrap() },
)
Memory::new_static(ty, tunables, base_ptr, base_capacity, slot, unsafe {
&mut *request.store.get().unwrap()
})
})() {
Ok(memory) => Ok((allocation_index, memory)),
Err(e) => {
Expand Down
Loading