Cache the JS memory view

This commit is contained in:
Amanieu d'Antras
2021-11-03 14:35:51 +00:00
committed by Manos Pitsidianakis
parent 714bac5650
commit d94745c9fc
2 changed files with 17 additions and 11 deletions

View File

@@ -75,10 +75,11 @@ extern "C" {
/// mutable from both host and WebAssembly.
///
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances>
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub struct Memory {
store: Store,
vm_memory: VMMemory,
view: js_sys::Uint8Array,
}
impl Memory {
@@ -107,9 +108,11 @@ impl Memory {
.map_err(|_e| MemoryError::Generic("Error while creating the memory".to_owned()))?;
let memory = VMMemory::new(js_memory, ty);
let view = js_sys::Uint8Array::new(&memory.memory.buffer());
Ok(Self {
store: store.clone(),
vm_memory: memory,
view,
})
}
@@ -231,14 +234,17 @@ impl Memory {
Ok(Pages(new_pages))
}
#[cfg(test)]
pub(crate) fn uint8view(&self) -> js_sys::Uint8Array {
js_sys::Uint8Array::new(&self.vm_memory.memory.buffer())
self.view.clone()
}
pub(crate) fn from_vm_export(store: &Store, vm_memory: VMMemory) -> Self {
let view = js_sys::Uint8Array::new(&vm_memory.memory.buffer());
Self {
store: store.clone(),
vm_memory,
view,
}
}
@@ -266,17 +272,16 @@ impl Memory {
/// This method is guaranteed to be safe (from the host side) in the face of
/// concurrent writes.
pub fn read(&self, offset: u64, buf: &mut [u8]) -> Result<(), MemoryAccessError> {
let view = self.uint8view();
let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?;
let len: u32 = buf
.len()
.try_into()
.map_err(|_| MemoryAccessError::Overflow)?;
let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?;
if end > view.length() {
if end > self.view.length() {
Err(MemoryAccessError::HeapOutOfBounds)?;
}
view.subarray(offset, end).copy_to(buf);
self.view.subarray(offset, end).copy_to(buf);
Ok(())
}
@@ -295,14 +300,13 @@ impl Memory {
offset: u64,
buf: &'a mut [MaybeUninit<u8>],
) -> Result<&'a mut [u8], MemoryAccessError> {
let view = self.uint8view();
let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?;
let len: u32 = buf
.len()
.try_into()
.map_err(|_| MemoryAccessError::Overflow)?;
let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?;
if end > view.length() {
if end > self.view.length() {
Err(MemoryAccessError::HeapOutOfBounds)?;
}
@@ -313,7 +317,7 @@ impl Memory {
}
let buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, buf.len()) };
view.subarray(offset, end).copy_to(buf);
self.view.subarray(offset, end).copy_to(buf);
Ok(buf)
}
@@ -325,17 +329,16 @@ impl Memory {
/// This method is guaranteed to be safe (from the host side) in the face of
/// concurrent reads/writes.
pub fn write(&self, offset: u64, data: &[u8]) -> Result<(), MemoryAccessError> {
let view = self.uint8view();
let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?;
let len: u32 = data
.len()
.try_into()
.map_err(|_| MemoryAccessError::Overflow)?;
let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?;
if end > view.length() {
if end > self.view.length() {
Err(MemoryAccessError::HeapOutOfBounds)?;
}
view.subarray(offset, end).copy_from(data);
self.view.subarray(offset, end).copy_from(data);
Ok(())
}
}

View File

@@ -17,7 +17,10 @@ pub unsafe trait MemorySize {
/// Zero value used for `WasmPtr::is_null`.
const ZERO: Self::Offset;
/// Convert an `Offset` to a `Native`.
fn offset_to_native(offset: Self::Offset) -> Self::Native;
/// Convert a `Native` to an `Offset`.
fn native_to_offset(native: Self::Native) -> Self::Offset;
}