Skip to content

Commit

Permalink
Merge pull request #3097 from wasmerio/memoryview_alternate_lifetime
Browse files Browse the repository at this point in the history
MemoryView lifetime tied to memory and not StoreRef
  • Loading branch information
syrusakbary authored Aug 12, 2022
2 parents a9302aa + 43581f0 commit 2ac8b77
Show file tree
Hide file tree
Showing 18 changed files with 192 additions and 171 deletions.
6 changes: 3 additions & 3 deletions lib/api/src/sys/externals/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::slice;
#[cfg(feature = "tracing")]
use tracing::warn;
use wasmer_types::Pages;
use wasmer_vm::{InternalStoreHandle, MemoryError, StoreHandle, StoreObjects, VMExtern, VMMemory};
use wasmer_vm::{InternalStoreHandle, MemoryError, StoreHandle, VMExtern, VMMemory};

use super::MemoryView;

Expand Down Expand Up @@ -79,7 +79,7 @@ impl Memory {

/// Creates a view into the memory that then allows for
/// read and write
pub fn view<'a>(&self, store: &'a impl AsStoreRef) -> MemoryView<'a> {
pub fn view<'a>(&'a self, store: &impl AsStoreRef) -> MemoryView<'a> {
MemoryView::new(self, store)
}

Expand Down Expand Up @@ -169,7 +169,7 @@ impl<'a> Exportable<'a> for Memory {
pub(crate) struct MemoryBuffer<'a> {
pub(crate) base: *mut u8,
pub(crate) len: usize,
pub(crate) marker: PhantomData<(&'a MemoryView<'a>, &'a StoreObjects)>,
pub(crate) marker: PhantomData<&'a MemoryView<'a>>,
}

impl<'a> MemoryBuffer<'a> {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/src/sys/externals/memory_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub struct MemoryView<'a> {
}

impl<'a> MemoryView<'a> {
pub(crate) fn new(memory: &Memory, store: &'a impl AsStoreRef) -> Self {
pub(crate) fn new(memory: &'a Memory, store: &impl AsStoreRef) -> Self {
let size = memory.handle.get(store.as_store_ref().objects()).size();

let definition = memory.handle.get(store.as_store_ref().objects()).vmmemory();
Expand Down
14 changes: 6 additions & 8 deletions lib/emscripten/src/env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,15 @@ pub fn ___build_environment(mut ctx: FunctionEnvMut<EmEnv>, environ: c_int) {
debug!("emscripten::___build_environment {}", environ);
const MAX_ENV_VALUES: u32 = 64;
const TOTAL_ENV_SIZE: u32 = 1024;
let environment =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), environ) as *mut c_int;
let memory = ctx.data().memory(0);
let environment = emscripten_memory_pointer!(memory.view(&ctx), environ) as *mut c_int;
let (mut pool_offset, env_ptr, mut pool_ptr) = unsafe {
let (pool_offset, _pool_slice): (u32, &mut [u8]) =
allocate_on_stack(&mut ctx, TOTAL_ENV_SIZE as u32);
let (env_offset, _env_slice): (u32, &mut [u8]) =
allocate_on_stack(&mut ctx, (MAX_ENV_VALUES * 4) as u32);
let env_ptr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), env_offset) as *mut c_int;
let pool_ptr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), pool_offset) as *mut u8;
let env_ptr = emscripten_memory_pointer!(memory.view(&ctx), env_offset) as *mut c_int;
let pool_ptr = emscripten_memory_pointer!(memory.view(&ctx), pool_offset) as *mut u8;
*env_ptr = pool_offset as i32;
*environment = env_offset as i32;

Expand Down Expand Up @@ -137,8 +135,8 @@ pub fn _pathconf(ctx: FunctionEnvMut<EmEnv>, path_addr: c_int, name: c_int) -> c
"emscripten::_pathconf {} {} - UNIMPLEMENTED",
path_addr, name
);
let _path =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), path_addr) as *const c_char;
let memory = ctx.data().memory(0);
let _path = emscripten_memory_pointer!(memory.view(&ctx), path_addr) as *const c_char;
match name {
0 => 32000,
1 | 2 | 3 => 255,
Expand Down
54 changes: 29 additions & 25 deletions lib/emscripten/src/env/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use wasmer::{FunctionEnvMut, WasmPtr};
pub fn _getenv(mut ctx: FunctionEnvMut<EmEnv>, name: i32) -> u32 {
debug!("emscripten::_getenv");

let name_addr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name) as *const c_char;
let memory = ctx.data().memory(0);
let name_addr = emscripten_memory_pointer!(memory.view(&ctx), name) as *const c_char;

debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });

Expand All @@ -34,10 +34,9 @@ pub fn _getenv(mut ctx: FunctionEnvMut<EmEnv>, name: i32) -> u32 {
pub fn _setenv(ctx: FunctionEnvMut<EmEnv>, name: c_int, value: c_int, overwrite: c_int) -> c_int {
debug!("emscripten::_setenv");

let name_addr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name) as *const c_char;
let value_addr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), value) as *const c_char;
let memory = ctx.data().memory(0);
let name_addr = emscripten_memory_pointer!(memory.view(&ctx), name) as *const c_char;
let value_addr = emscripten_memory_pointer!(memory.view(&ctx), value) as *const c_char;

debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });
debug!("=> value({:?})", unsafe { CStr::from_ptr(value_addr) });
Expand All @@ -49,8 +48,8 @@ pub fn _setenv(ctx: FunctionEnvMut<EmEnv>, name: c_int, value: c_int, overwrite:
pub fn _putenv(ctx: FunctionEnvMut<EmEnv>, name: c_int) -> c_int {
debug!("emscripten::_putenv");

let name_addr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name) as *const c_char;
let memory = ctx.data().memory(0);
let name_addr = emscripten_memory_pointer!(memory.view(&ctx), name) as *const c_char;

debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });

Expand All @@ -61,8 +60,8 @@ pub fn _putenv(ctx: FunctionEnvMut<EmEnv>, name: c_int) -> c_int {
pub fn _unsetenv(ctx: FunctionEnvMut<EmEnv>, name: c_int) -> c_int {
debug!("emscripten::_unsetenv");

let name_addr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name) as *const c_char;
let memory = ctx.data().memory(0);
let name_addr = emscripten_memory_pointer!(memory.view(&ctx), name) as *const c_char;

debug!("=> name({:?})", unsafe { CStr::from_ptr(name_addr) });

Expand All @@ -86,8 +85,9 @@ pub fn _getpwnam(mut ctx: FunctionEnvMut<EmEnv>, name_ptr: c_int) -> c_int {
pw_shell: u32,
}

let memory = ctx.data().memory(0);
let name = unsafe {
let memory = ctx.data().memory_view(0, &ctx);
let memory = memory.view(&ctx);
let memory_name_ptr = emscripten_memory_pointer!(&memory, name_ptr) as *const c_char;
CStr::from_ptr(memory_name_ptr)
};
Expand All @@ -96,7 +96,7 @@ pub fn _getpwnam(mut ctx: FunctionEnvMut<EmEnv>, name_ptr: c_int) -> c_int {
let passwd = &*libc_getpwnam(name.as_ptr());
let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::<GuestPasswd>() as _);

let memory = ctx.data().memory_view(0, &ctx);
let memory = memory.view(&ctx);
let passwd_struct_ptr =
emscripten_memory_pointer!(&memory, passwd_struct_offset) as *mut GuestPasswd;
(*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(&mut ctx, passwd.pw_name);
Expand All @@ -123,9 +123,10 @@ pub fn _getgrnam(mut ctx: FunctionEnvMut<EmEnv>, name_ptr: c_int) -> c_int {
gr_mem: u32,
}

let memory = ctx.data().memory(0);
let name = unsafe {
let memory_name_ptr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name_ptr) as *const c_char;
emscripten_memory_pointer!(memory.view(&ctx), name_ptr) as *const c_char;
CStr::from_ptr(memory_name_ptr)
};

Expand All @@ -134,8 +135,7 @@ pub fn _getgrnam(mut ctx: FunctionEnvMut<EmEnv>, name_ptr: c_int) -> c_int {
let group_struct_offset = call_malloc(&mut ctx, mem::size_of::<GuestGroup>() as _);

let group_struct_ptr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), group_struct_offset)
as *mut GuestGroup;
emscripten_memory_pointer!(memory.view(&ctx), group_struct_offset) as *mut GuestGroup;
(*group_struct_ptr).gr_name = copy_cstr_into_wasm(&mut ctx, group.gr_name);
(*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(&mut ctx, group.gr_passwd);
(*group_struct_ptr).gr_gid = group.gr_gid;
Expand All @@ -158,7 +158,8 @@ pub fn _gai_strerror(mut ctx: FunctionEnvMut<EmEnv>, ecode: i32) -> i32 {
let cstr = unsafe { std::ffi::CStr::from_ptr(libc::gai_strerror(ecode)) };
let bytes = cstr.to_bytes_with_nul();
let string_on_guest: WasmPtr<c_char> = call_malloc_with_cast(&mut ctx, bytes.len() as _);
let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let memory = memory.view(&ctx);

let writer = string_on_guest.slice(&memory, bytes.len() as _).unwrap();
for (i, byte) in bytes.iter().enumerate() {
Expand Down Expand Up @@ -195,10 +196,8 @@ pub fn _getaddrinfo(
let hints = if hints_ptr.is_null() {
None
} else {
let hints_guest = hints_ptr
.deref(&ctx.data().memory_view(0, &ctx))
.read()
.unwrap();
let memory = ctx.data().memory(0);
let hints_guest = hints_ptr.deref(&memory.view(&ctx)).read().unwrap();
Some(addrinfo {
ai_flags: hints_guest.ai_flags,
ai_family: hints_guest.ai_family,
Expand Down Expand Up @@ -252,7 +251,8 @@ pub fn _getaddrinfo(

// connect list
if let Some(prev_guest) = previous_guest_node {
let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let memory = memory.view(&ctx);
let derefed_prev_guest = prev_guest.deref(&memory);
let mut pg = derefed_prev_guest.read().unwrap();
pg.ai_next = current_guest_node_ptr;
Expand All @@ -268,7 +268,8 @@ pub fn _getaddrinfo(
let guest_sockaddr_ptr: WasmPtr<EmSockAddr> =
call_malloc_with_cast(&mut ctx, host_addrlen as _);

let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let memory = memory.view(&ctx);
let derefed_guest_sockaddr = guest_sockaddr_ptr.deref(&memory);
let mut gs = derefed_guest_sockaddr.read().unwrap();
gs.sa_family = (*host_sockaddr_ptr).sa_family as i16;
Expand All @@ -288,7 +289,8 @@ pub fn _getaddrinfo(
let guest_canonname: WasmPtr<c_char> =
call_malloc_with_cast(&mut ctx, str_size as _);

let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let memory = memory.view(&ctx);
let guest_canonname_writer =
guest_canonname.slice(&memory, str_size as _).unwrap();
for (i, b) in canonname_bytes.iter().enumerate() {
Expand All @@ -304,7 +306,8 @@ pub fn _getaddrinfo(
}
};

let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let memory = memory.view(&ctx);
let derefed_current_guest_node = current_guest_node_ptr.deref(&memory);
let mut cgn = derefed_current_guest_node.read().unwrap();
cgn.ai_flags = (*current_host_node).ai_flags;
Expand All @@ -325,8 +328,9 @@ pub fn _getaddrinfo(
head_of_list.unwrap_or_else(|| WasmPtr::new(0))
};

let memory = ctx.data().memory(0);
res_val_ptr
.deref(&ctx.data().memory_view(0, &ctx))
.deref(&memory.view(&ctx))
.write(head_of_list)
.unwrap();

Expand Down
32 changes: 19 additions & 13 deletions lib/emscripten/src/env/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ extern "C" {
/// emscripten: _getenv // (name: *const char) -> *const c_char;
pub fn _getenv(mut ctx: FunctionEnvMut<EmEnv>, name: u32) -> u32 {
debug!("emscripten::_getenv");
let memory = ctx.data().memory_view(0, &ctx);
let name_string = read_string_from_wasm(&memory, name);
let memory = ctx.data().memory(0);
let view = memory.view(&ctx);
let name_string = read_string_from_wasm(&view, name);
debug!("=> name({:?})", name_string);
let c_str = unsafe { getenv(name_string.as_ptr() as *const libc::c_char) };
if c_str.is_null() {
Expand All @@ -32,10 +33,11 @@ pub fn _getenv(mut ctx: FunctionEnvMut<EmEnv>, name: u32) -> u32 {
/// emscripten: _setenv // (name: *const char, name: *const value, overwrite: int);
pub fn _setenv(ctx: FunctionEnvMut<EmEnv>, name: u32, value: u32, _overwrite: u32) -> c_int {
debug!("emscripten::_setenv");
let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let view = memory.view(&ctx);
// setenv does not exist on windows, so we hack it with _putenv
let name = read_string_from_wasm(&memory, name);
let value = read_string_from_wasm(&memory, value);
let name = read_string_from_wasm(&view, name);
let value = read_string_from_wasm(&view, value);
let putenv_string = format!("{}={}", name, value);
let putenv_cstring = CString::new(putenv_string).unwrap();
let putenv_raw_ptr = putenv_cstring.as_ptr();
Expand All @@ -47,8 +49,9 @@ pub fn _setenv(ctx: FunctionEnvMut<EmEnv>, name: u32, value: u32, _overwrite: u3
/// emscripten: _putenv // (name: *const char);
pub fn _putenv(ctx: FunctionEnvMut<EmEnv>, name: c_int) -> c_int {
debug!("emscripten::_putenv");
let memory = ctx.data().memory_view(0, &ctx);
let name_addr = emscripten_memory_pointer!(&memory, name) as *const c_char;
let memory = ctx.data().memory(0);
let view = memory.view(&ctx);
let name_addr = emscripten_memory_pointer!(&view, name) as *const c_char;
debug!("=> name({:?})", unsafe {
std::ffi::CStr::from_ptr(name_addr)
});
Expand All @@ -58,8 +61,9 @@ pub fn _putenv(ctx: FunctionEnvMut<EmEnv>, name: c_int) -> c_int {
/// emscripten: _unsetenv // (name: *const char);
pub fn _unsetenv(ctx: FunctionEnvMut<EmEnv>, name: u32) -> c_int {
debug!("emscripten::_unsetenv");
let memory = ctx.data().memory_view(0, &ctx);
let name = read_string_from_wasm(&memory, name);
let memory = ctx.data().memory(0);
let view = memory.view(&ctx);
let name = read_string_from_wasm(&view, name);
// no unsetenv on windows, so use putenv with an empty value
let unsetenv_string = format!("{}=", name);
let unsetenv_cstring = CString::new(unsetenv_string).unwrap();
Expand Down Expand Up @@ -88,9 +92,10 @@ pub fn _getpwnam(mut ctx: FunctionEnvMut<EmEnv>, name_ptr: c_int) -> c_int {
// stub this in windows as it is not valid
unsafe {
let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::<GuestPasswd>() as _);
let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let view = memory.view(&ctx);
let passwd_struct_ptr =
emscripten_memory_pointer!(&memory, passwd_struct_offset) as *mut GuestPasswd;
emscripten_memory_pointer!(&view, passwd_struct_offset) as *mut GuestPasswd;
(*passwd_struct_ptr).pw_name = 0;
(*passwd_struct_ptr).pw_passwd = 0;
(*passwd_struct_ptr).pw_gecos = 0;
Expand Down Expand Up @@ -120,9 +125,10 @@ pub fn _getgrnam(mut ctx: FunctionEnvMut<EmEnv>, name_ptr: c_int) -> c_int {
// stub the group struct as it is not supported on windows
unsafe {
let group_struct_offset = call_malloc(&mut ctx, mem::size_of::<GuestGroup>() as _);
let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let view = memory.view(&ctx);
let group_struct_ptr =
emscripten_memory_pointer!(&memory, group_struct_offset) as *mut GuestGroup;
emscripten_memory_pointer!(&view, group_struct_offset) as *mut GuestGroup;
(*group_struct_ptr).gr_name = 0;
(*group_struct_ptr).gr_passwd = 0;
(*group_struct_ptr).gr_gid = 0;
Expand Down
3 changes: 2 additions & 1 deletion lib/emscripten/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use wasmer::{FunctionEnvMut, WasmPtr};

pub fn execvp(ctx: FunctionEnvMut<EmEnv>, command_name_offset: u32, argv_offset: u32) -> i32 {
// a single reference to re-use
let emscripten_memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let emscripten_memory = memory.view(&ctx);

// read command name as string
let command_name_string_vec = WasmPtr::<u8>::new(command_name_offset)
Expand Down
10 changes: 6 additions & 4 deletions lib/emscripten/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ pub fn getprotobynumber(_ctx: FunctionEnvMut<EmEnv>, _one: i32) -> i32 {
/// sigdelset
pub fn sigdelset(ctx: FunctionEnvMut<EmEnv>, set: i32, signum: i32) -> i32 {
debug!("emscripten::sigdelset");
let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let view = memory.view(&ctx);
#[allow(clippy::cast_ptr_alignment)]
let ptr = emscripten_memory_pointer!(&memory, set) as *mut i32;
let ptr = emscripten_memory_pointer!(&view, set) as *mut i32;

unsafe { *ptr &= !(1 << (signum - 1)) }

Expand All @@ -40,9 +41,10 @@ pub fn sigdelset(ctx: FunctionEnvMut<EmEnv>, set: i32, signum: i32) -> i32 {
/// sigfillset
pub fn sigfillset(ctx: FunctionEnvMut<EmEnv>, set: i32) -> i32 {
debug!("emscripten::sigfillset");
let memory = ctx.data().memory_view(0, &ctx);
let memory = ctx.data().memory(0);
let view = memory.view(&ctx);
#[allow(clippy::cast_ptr_alignment)]
let ptr = emscripten_memory_pointer!(&memory, set) as *mut i32;
let ptr = emscripten_memory_pointer!(&view, set) as *mut i32;

unsafe {
*ptr = -1;
Expand Down
6 changes: 3 additions & 3 deletions lib/emscripten/src/io/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ pub fn putchar(_ctx: FunctionEnvMut<EmEnv>, chr: i32) {
pub fn printf(ctx: FunctionEnvMut<EmEnv>, memory_offset: i32, extra: i32) -> i32 {
debug!("emscripten::printf {}, {}", memory_offset, extra);
unsafe {
let addr = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), memory_offset) as _;
let addr = emscripten_memory_pointer!(ctx.data().memory(0).view(&ctx), memory_offset) as _;
_printf(addr, extra)
}
}

/// chroot
pub fn chroot(ctx: FunctionEnvMut<EmEnv>, name_ptr: i32) -> i32 {
debug!("emscripten::chroot");
let name = emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), name_ptr) as *const i8;
let name = emscripten_memory_pointer!(ctx.data().memory(0).view(&ctx), name_ptr) as *const i8;
unsafe { _chroot(name as *const _) }
}

Expand All @@ -47,7 +47,7 @@ pub fn getpwuid(mut ctx: FunctionEnvMut<EmEnv>, uid: i32) -> i32 {
let passwd = &*_getpwuid(uid as _);
let passwd_struct_offset = call_malloc(&mut ctx, mem::size_of::<GuestPasswd>() as _);
let passwd_struct_ptr =
emscripten_memory_pointer!(ctx.data().memory_view(0, &ctx), passwd_struct_offset)
emscripten_memory_pointer!(ctx.data().memory(0).view(&ctx), passwd_struct_offset)
as *mut GuestPasswd;
assert_eq!(
passwd_struct_ptr as usize % std::mem::align_of::<GuestPasswd>(),
Expand Down
11 changes: 3 additions & 8 deletions lib/emscripten/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ use std::f64;
use std::path::PathBuf;
use std::sync::{Arc, Mutex, RwLock};
use wasmer::{
imports, namespace, AsStoreMut, AsStoreRef, ExportError, Exports, Function, FunctionEnv,
FunctionEnvMut, FunctionType, Global, Imports, Instance, Memory, MemoryType, MemoryView,
Module, Pages, RuntimeError, Table, TableType, TypedFunction, Value, WasmPtr,
imports, namespace, AsStoreMut, ExportError, Exports, Function, FunctionEnv, FunctionEnvMut,
FunctionType, Global, Imports, Instance, Memory, MemoryType, Module, Pages, RuntimeError,
Table, TableType, TypedFunction, Value, WasmPtr,
};
use wasmer_types::Type as ValType;

Expand Down Expand Up @@ -108,11 +108,6 @@ impl EmEnv {
(&*self.memory.read().unwrap()).as_ref().cloned().unwrap()
}

/// Get a reference to the memory view
pub fn memory_view<'a>(&self, mem_idx: u32, store: &'a impl AsStoreRef) -> MemoryView<'a> {
self.memory(mem_idx).view(store)
}

pub fn set_functions(&mut self, funcs: EmscriptenFunctions) {
self.funcs = Arc::new(Mutex::new(funcs));
}
Expand Down
Loading

0 comments on commit 2ac8b77

Please sign in to comment.