From c3576e1b3f7de537c00d357d08fa6762e50f95b6 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Fri, 10 Feb 2023 16:03:43 -0800 Subject: [PATCH] Unified ptr::WasmPtr into js/sys --- lib/api/src/js/mod.rs | 2 - lib/api/src/js/ptr.rs | 276 ----------------------------------- lib/api/src/lib.rs | 3 +- lib/api/src/{sys => }/ptr.rs | 10 +- lib/api/src/sys/mod.rs | 2 - 5 files changed, 8 insertions(+), 285 deletions(-) delete mode 100644 lib/api/src/js/ptr.rs rename lib/api/src/{sys => }/ptr.rs (97%) diff --git a/lib/api/src/js/mod.rs b/lib/api/src/js/mod.rs index 9c42bfa09..e7d7a426e 100644 --- a/lib/api/src/js/mod.rs +++ b/lib/api/src/js/mod.rs @@ -34,7 +34,6 @@ pub(crate) mod module; #[cfg(feature = "wasm-types-polyfill")] mod module_info_polyfill; mod native; -mod ptr; pub(crate) mod store; mod trap; mod types; @@ -53,7 +52,6 @@ pub use crate::js::imports::Imports; pub use crate::js::instance::Instance; pub use crate::js::module::{Module, ModuleTypeHints}; pub use crate::js::native::TypedFunction; -pub use crate::js::ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64}; pub use crate::js::store::StoreObjects; pub use crate::js::trap::RuntimeError; pub use crate::js::types::ValType as Type; diff --git a/lib/api/src/js/ptr.rs b/lib/api/src/js/ptr.rs deleted file mode 100644 index 4a3688489..000000000 --- a/lib/api/src/js/ptr.rs +++ /dev/null @@ -1,276 +0,0 @@ -use crate::js::{externals::MemoryView, FromToNativeWasmType}; -use crate::mem_access::{MemoryAccessError, WasmRef, WasmSlice}; -use crate::store::AsStoreRef; -use crate::NativeWasmTypeInto; -use std::convert::TryFrom; -use std::{fmt, marker::PhantomData, mem}; -pub use wasmer_types::Memory32; -pub use wasmer_types::Memory64; -pub use wasmer_types::MemorySize; -use wasmer_types::ValueType; - -/// Alias for `WasmPtr. -pub type WasmPtr64 = WasmPtr; - -/// A zero-cost type that represents a pointer to something in Wasm linear -/// memory. -/// -/// This type can be used directly in the host function arguments: -/// ``` -/// # use wasmer::Memory; -/// # use wasmer::WasmPtr; -/// pub fn host_import(memory: Memory, ptr: WasmPtr) { -/// let derefed_ptr = ptr.deref(&memory); -/// let inner_val: u32 = derefed_ptr.read().expect("pointer in bounds"); -/// println!("Got {} from Wasm memory address 0x{:X}", inner_val, ptr.offset()); -/// // update the value being pointed to -/// derefed_ptr.write(inner_val + 1).expect("pointer in bounds"); -/// } -/// ``` -/// -/// This type can also be used with primitive-filled structs, but be careful of -/// guarantees required by `ValueType`. -/// ``` -/// # use wasmer::Memory; -/// # use wasmer::WasmPtr; -/// # use wasmer::ValueType; -/// -/// // This is safe as the 12 bytes represented by this struct -/// // are valid for all bit combinations. -/// #[derive(Copy, Clone, Debug, ValueType)] -/// #[repr(C)] -/// struct V3 { -/// x: f32, -/// y: f32, -/// z: f32 -/// } -/// -/// fn update_vector_3(memory: Memory, ptr: WasmPtr) { -/// let derefed_ptr = ptr.deref(&memory); -/// let mut inner_val: V3 = derefed_ptr.read().expect("pointer in bounds"); -/// println!("Got {:?} from Wasm memory address 0x{:X}", inner_val, ptr.offset()); -/// // update the value being pointed to -/// inner_val.x = 10.4; -/// derefed_ptr.write(inner_val).expect("pointer in bounds"); -/// } -/// ``` -#[repr(transparent)] -pub struct WasmPtr { - offset: M::Offset, - _phantom: PhantomData<*mut T>, -} - -impl WasmPtr { - /// Create a new `WasmPtr` at the given offset. - #[inline] - pub fn new(offset: M::Offset) -> Self { - Self { - offset, - _phantom: PhantomData, - } - } - - /// Get the offset into Wasm linear memory for this `WasmPtr`. - #[inline] - pub fn offset(&self) -> M::Offset { - self.offset - } - - /// Casts this `WasmPtr` to a `WasmPtr` of a different type. - #[inline] - pub fn cast(self) -> WasmPtr { - WasmPtr { - offset: self.offset, - _phantom: PhantomData, - } - } - - /// Returns a null `UserPtr`. - #[inline] - pub fn null() -> Self { - WasmPtr::new(M::ZERO) - } - - /// Checks whether the `WasmPtr` is null. - #[inline] - pub fn is_null(self) -> bool { - self.offset.into() == 0 - } - - /// Calculates an offset from the current pointer address. The argument is - /// in units of `T`. - /// - /// This method returns an error if an address overflow occurs. - #[inline] - pub fn add_offset(self, offset: M::Offset) -> Result { - let base = self.offset.into(); - let index = offset.into(); - let offset = index - .checked_mul(mem::size_of::() as u64) - .ok_or(MemoryAccessError::Overflow)?; - let address = base - .checked_add(offset) - .ok_or(MemoryAccessError::Overflow)?; - let address = M::Offset::try_from(address).map_err(|_| MemoryAccessError::Overflow)?; - Ok(WasmPtr::new(address)) - } - - /// Calculates an offset from the current pointer address. The argument is - /// in units of `T`. - /// - /// This method returns an error if an address overflow occurs. - #[inline] - pub fn sub_offset(self, offset: M::Offset) -> Result { - let base = self.offset.into(); - let index = offset.into(); - let offset = index - .checked_mul(mem::size_of::() as u64) - .ok_or(MemoryAccessError::Overflow)?; - let address = base - .checked_sub(offset) - .ok_or(MemoryAccessError::Overflow)?; - let address = M::Offset::try_from(address).map_err(|_| MemoryAccessError::Overflow)?; - Ok(WasmPtr::new(address)) - } -} - -impl WasmPtr { - /// Creates a `WasmRef` from this `WasmPtr` which allows reading and - /// mutating of the value being pointed to. - #[inline] - pub fn deref<'a>(self, view: &'a MemoryView) -> WasmRef<'a, T> { - WasmRef::new(view, self.offset.into()) - } - - /// Reads the address pointed to by this `WasmPtr` in a memory. - #[inline] - pub fn read(self, view: &MemoryView) -> Result { - self.deref(view).read() - } - - /// Writes to the address pointed to by this `WasmPtr` in a memory. - #[inline] - pub fn write(self, view: &MemoryView, val: T) -> Result<(), MemoryAccessError> { - self.deref(view).write(val) - } - - /// Creates a `WasmSlice` starting at this `WasmPtr` which allows reading - /// and mutating of an array of value being pointed to. - /// - /// Returns a `MemoryAccessError` if the slice length overflows a 64-bit - /// address. - #[inline] - pub fn slice<'a>( - self, - view: &'a MemoryView, - len: M::Offset, - ) -> Result, MemoryAccessError> { - WasmSlice::new(view, self.offset.into(), len.into()) - } - - /// Reads a sequence of values from this `WasmPtr` until a value that - /// matches the given condition is found. - /// - /// This last value is not included in the returned vector. - #[inline] - pub fn read_until<'a>( - self, - view: &'a MemoryView, - mut end: impl FnMut(&T) -> bool, - ) -> Result, MemoryAccessError> { - let mut vec = Vec::new(); - for i in 0u64.. { - let i = M::Offset::try_from(i).map_err(|_| MemoryAccessError::Overflow)?; - let val = self.add_offset(i)?.deref(view).read()?; - if end(&val) { - break; - } - vec.push(val); - } - Ok(vec) - } -} - -impl WasmPtr { - /// Reads a UTF-8 string from the `WasmPtr` with the given length. - /// - /// This method is safe to call even if the memory is being concurrently - /// modified. - #[inline] - pub fn read_utf8_string<'a>( - self, - view: &'a MemoryView, - len: M::Offset, - ) -> Result { - let vec = self.slice(view, len)?.read_to_vec()?; - Ok(String::from_utf8(vec)?) - } - - /// Reads a null-terminated UTF-8 string from the `WasmPtr`. - /// - /// This method is safe to call even if the memory is being concurrently - /// modified. - #[inline] - pub fn read_utf8_string_with_nul<'a>( - self, - view: &'a MemoryView, - ) -> Result { - let vec = self.read_until(view, |&byte| byte == 0)?; - Ok(String::from_utf8(vec)?) - } -} - -unsafe impl FromToNativeWasmType for WasmPtr -where - ::Native: NativeWasmTypeInto, -{ - type Native = M::Native; - - fn to_native(self) -> Self::Native { - M::offset_to_native(self.offset) - } - fn from_native(n: Self::Native) -> Self { - Self { - offset: M::native_to_offset(n), - _phantom: PhantomData, - } - } - #[inline] - fn is_from_store(&self, _store: &impl AsStoreRef) -> bool { - true // in Javascript there are no different stores - } -} - -unsafe impl ValueType for WasmPtr { - fn zero_padding_bytes(&self, _bytes: &mut [mem::MaybeUninit]) {} -} - -impl Clone for WasmPtr { - fn clone(&self) -> Self { - Self { - offset: self.offset, - _phantom: PhantomData, - } - } -} - -impl Copy for WasmPtr {} - -impl PartialEq for WasmPtr { - fn eq(&self, other: &Self) -> bool { - self.offset.into() == other.offset.into() - } -} - -impl Eq for WasmPtr {} - -impl fmt::Debug for WasmPtr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "WasmPtr(offset: {}, pointer: {:#x})", - self.offset.into(), - self.offset.into() - ) - } -} diff --git a/lib/api/src/lib.rs b/lib/api/src/lib.rs index 06625476e..2e0ac4b77 100644 --- a/lib/api/src/lib.rs +++ b/lib/api/src/lib.rs @@ -435,6 +435,7 @@ mod function_env; mod mem_access; mod module; mod native_type; +mod ptr; mod store; #[cfg(feature = "sys")] @@ -455,7 +456,7 @@ pub use function_env::{FunctionEnv, FunctionEnvMut}; pub use mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter}; pub use module::{IoCompileError, Module}; pub use native_type::NativeWasmTypeInto; - +pub use ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64}; pub use store::{AsStoreMut, AsStoreRef, OnCalledHandler, Store, StoreId, StoreMut, StoreRef}; #[cfg(feature = "sys")] pub use store::{TrapHandlerFn, Tunables}; diff --git a/lib/api/src/sys/ptr.rs b/lib/api/src/ptr.rs similarity index 97% rename from lib/api/src/sys/ptr.rs rename to lib/api/src/ptr.rs index 586cf2797..82609acdf 100644 --- a/lib/api/src/sys/ptr.rs +++ b/lib/api/src/ptr.rs @@ -1,13 +1,11 @@ use crate::mem_access::{MemoryAccessError, WasmRef, WasmSlice}; -use crate::sys::{externals::MemoryView, FromToNativeWasmType}; -use crate::NativeWasmTypeInto; +use crate::{AsStoreRef, FromToNativeWasmType, MemoryView, NativeWasmTypeInto}; use std::convert::TryFrom; use std::{fmt, marker::PhantomData, mem}; -use wasmer_types::ValueType; - pub use wasmer_types::Memory32; pub use wasmer_types::Memory64; pub use wasmer_types::MemorySize; +use wasmer_types::ValueType; /// Alias for `WasmPtr. pub type WasmPtr64 = WasmPtr; @@ -236,6 +234,10 @@ where _phantom: PhantomData, } } + #[inline] + fn is_from_store(&self, _store: &impl AsStoreRef) -> bool { + true // in Javascript there are no different stores + } } unsafe impl ValueType for WasmPtr { diff --git a/lib/api/src/sys/mod.rs b/lib/api/src/sys/mod.rs index 47a3f3314..7a24f5791 100644 --- a/lib/api/src/sys/mod.rs +++ b/lib/api/src/sys/mod.rs @@ -6,7 +6,6 @@ mod imports; mod instance; pub(crate) mod module; mod native; -mod ptr; mod tunables; mod value; @@ -19,7 +18,6 @@ pub use crate::sys::imports::Imports; pub use crate::sys::instance::{Instance, InstantiationError}; pub use crate::sys::native::TypedFunction; -pub use crate::sys::ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64}; pub use crate::sys::tunables::BaseTunables; pub use crate::sys::value::Value; pub use target_lexicon::{Architecture, CallingConvention, OperatingSystem, Triple, HOST};