Skip to content

Commit

Permalink
Improved API based on feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
syrusakbary committed Jul 2, 2021
1 parent a039af4 commit 1a8952e
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 52 deletions.
27 changes: 12 additions & 15 deletions lib/api/src/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,22 +149,19 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
{
return None;
}
let cell_ptrs = unsafe {
let cell_ptr = align_pointer(
memory.view::<u8>().as_ptr().add(self.offset as usize) as usize,
mem::align_of::<T>(),
) as *const Cell<T>;
&std::slice::from_raw_parts(cell_ptr, slice_full_len)[index as usize..slice_full_len]
};

Some(
(0..(length as usize))
.map(|i| unsafe {
let cell_ptr = align_pointer(
memory
.view::<u8>()
.as_ptr()
.add((self.offset as usize + i * item_size))
as usize,
mem::align_of::<T>(),
) as *const Cell<T>;
WasmCell::new(&*cell_ptr)
})
.collect::<Vec<_>>(),
)
let wasm_cells = cell_ptrs
.iter()
.map(|ptr| WasmCell::new(ptr))
.collect::<Vec<_>>();
Some(wasm_cells)
}

/// Get a UTF-8 string from the `WasmPtr` with the given length.
Expand Down
2 changes: 1 addition & 1 deletion lib/emscripten/src/env/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ pub fn _getaddrinfo(
node_ptr
.deref(&memory)
.map(|_np| {
// unimplemented!();
unimplemented!();
// std::ffi::CStr::from_ptr(np as *const Cell<c_char> as *const c_char)
// .to_string_lossy()
})
Expand Down
34 changes: 24 additions & 10 deletions lib/types/src/memory_view.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::lib::std::cell::Cell;
use crate::lib::std::marker::PhantomData;
use crate::lib::std::ops::Deref;
use crate::lib::std::ops::{Bound, RangeBounds};
use crate::lib::std::slice;
use crate::lib::std::sync::atomic::{
AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicU16, AtomicU32, AtomicU64, AtomicU8,
Expand Down Expand Up @@ -48,6 +49,8 @@ impl Atomicity for NonAtomically {}
/// A view into a memory.
pub struct MemoryView<'a, T: 'a, A = NonAtomically> {
ptr: *mut T,
// Note: the length is in the terms of `size::<T>()`.
// The total length in memory is `size::<T>() * length`.
length: usize,
_phantom: PhantomData<(&'a [Cell<T>], A)>,
}
Expand All @@ -66,12 +69,20 @@ where
}

/// Creates a subarray view from this MemoryView.
pub fn subarray(&self, start: u32, end: u32) -> Self {
assert!(start <= end);
assert!((end as usize) < self.length);
pub fn subarray(&self, range: impl RangeBounds<usize>) -> Self {
let start: usize = match range.start_bound() {
Bound::Unbounded => 0,
Bound::Included(start) => *start,
Bound::Excluded(start) => *start + 1,
};
let end: usize = match range.end_bound() {
Bound::Unbounded => self.length,
Bound::Included(end) => *end,
Bound::Excluded(end) => *end - 1,
};
Self {
ptr: unsafe { self.ptr.add(start as usize) },
length: (end - start) as usize,
ptr: unsafe { self.ptr.add(start) },
length: (end - start),
_phantom: PhantomData,
}
}
Expand All @@ -80,15 +91,18 @@ where
///
/// This function will efficiently copy the memory from within the wasm
/// module’s own linear memory to this typed array.
pub fn copy_from(&self, src: &[T]) {
///
/// # Safety
///
/// This method is unsafe because the caller will need to make sure
/// there are no data races when copying memory into the view.
pub unsafe fn copy_from(&self, src: &[T]) {
assert!(
src.len() == self.length,
"The source length must match the MemoryView length"
);
unsafe {
for (i, byte) in src.iter().enumerate() {
*self.ptr.offset(i as isize) = *byte;
}
for (i, byte) in src.iter().enumerate() {
*self.ptr.offset(i as isize) = *byte;
}
}
}
Expand Down
63 changes: 37 additions & 26 deletions lib/wasi/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub use windows::*;
fn write_bytes_inner<T: Write>(
mut write_loc: T,
memory: &Memory,
iovs_arr_cell: Vec<WasmCell<__wasi_ciovec_t>>,
iovs_arr_cell: &[WasmCell<__wasi_ciovec_t>],
) -> Result<u32, __wasi_errno_t> {
let mut bytes_written = 0;
for iov in iovs_arr_cell {
Expand All @@ -65,7 +65,7 @@ fn write_bytes_inner<T: Write>(
fn write_bytes<T: Write>(
mut write_loc: T,
memory: &Memory,
iovs_arr_cell: Vec<WasmCell<__wasi_ciovec_t>>,
iovs_arr_cell: &[WasmCell<__wasi_ciovec_t>],
) -> Result<u32, __wasi_errno_t> {
let result = write_bytes_inner(&mut write_loc, memory, iovs_arr_cell);
write_loc.flush();
Expand All @@ -75,18 +75,27 @@ fn write_bytes<T: Write>(
fn read_bytes<T: Read>(
mut reader: T,
memory: &Memory,
iovs_arr_cell: Vec<WasmCell<__wasi_iovec_t>>,
iovs_arr_cell: &[WasmCell<__wasi_iovec_t>],
) -> Result<u32, __wasi_errno_t> {
let mut bytes_read = 0;

// We allocate the raw_bytes first once instead of
// N times in the loop.
let mut raw_bytes: Vec<u8> = vec![0; 1024];

for iov in iovs_arr_cell {
let iov_inner = iov.get();
let mut raw_bytes: Vec<u8> = vec![0; iov_inner.buf_len as usize];
raw_bytes.clear();
raw_bytes.resize(iov_inner.buf_len as usize, 0);
bytes_read += reader.read(&mut raw_bytes).map_err(|_| __WASI_EIO)? as u32;
memory
.view::<u8>()
.subarray(iov_inner.buf, iov_inner.buf + iov_inner.buf_len)
.copy_from(&raw_bytes);
unsafe {
memory
.view::<u8>()
.subarray(
iov_inner.buf as usize..=(iov_inner.buf as usize + iov_inner.buf_len as usize),
)
.copy_from(&raw_bytes[..iov_inner.buf_len as usize]);
}
}
Ok(bytes_read)
}
Expand Down Expand Up @@ -661,7 +670,7 @@ pub fn fd_pread(
if let Some(ref mut stdin) =
wasi_try!(state.fs.stdin_mut().map_err(WasiFsError::into_wasi_err))
{
wasi_try!(read_bytes(stdin, memory, iov_cells))
wasi_try!(read_bytes(stdin, memory, &iov_cells))
} else {
return __WASI_EBADF;
}
Expand All @@ -688,15 +697,15 @@ pub fn fd_pread(
h.seek(std::io::SeekFrom::Start(offset as u64)).ok(),
__WASI_EIO
);
wasi_try!(read_bytes(h, memory, iov_cells))
wasi_try!(read_bytes(h, memory, &iov_cells))
} else {
return __WASI_EINVAL;
}
}
Kind::Dir { .. } | Kind::Root { .. } => return __WASI_EISDIR,
Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_pread"),
Kind::Buffer { buffer } => {
wasi_try!(read_bytes(&buffer[(offset as usize)..], memory, iov_cells))
wasi_try!(read_bytes(&buffer[(offset as usize)..], memory, &iov_cells))
}
}
}
Expand Down Expand Up @@ -810,7 +819,7 @@ pub fn fd_pwrite(
if let Some(ref mut stdout) =
wasi_try!(state.fs.stdout_mut().map_err(WasiFsError::into_wasi_err))
{
wasi_try!(write_bytes(stdout, memory, iovs_arr_cell))
wasi_try!(write_bytes(stdout, memory, &iovs_arr_cell))
} else {
return __WASI_EBADF;
}
Expand All @@ -819,7 +828,7 @@ pub fn fd_pwrite(
if let Some(ref mut stderr) =
wasi_try!(state.fs.stderr_mut().map_err(WasiFsError::into_wasi_err))
{
wasi_try!(write_bytes(stderr, memory, iovs_arr_cell))
wasi_try!(write_bytes(stderr, memory, &iovs_arr_cell))
} else {
return __WASI_EBADF;
}
Expand All @@ -840,7 +849,7 @@ pub fn fd_pwrite(
Kind::File { handle, .. } => {
if let Some(handle) = handle {
handle.seek(std::io::SeekFrom::Start(offset as u64));
wasi_try!(write_bytes(handle, memory, iovs_arr_cell))
wasi_try!(write_bytes(handle, memory, &iovs_arr_cell))
} else {
return __WASI_EINVAL;
}
Expand All @@ -854,7 +863,7 @@ pub fn fd_pwrite(
wasi_try!(write_bytes(
&mut buffer[(offset as usize)..],
memory,
iovs_arr_cell
&iovs_arr_cell
))
}
}
Expand Down Expand Up @@ -896,7 +905,7 @@ pub fn fd_read(
if let Some(ref mut stdin) =
wasi_try!(state.fs.stdin_mut().map_err(WasiFsError::into_wasi_err))
{
wasi_try!(read_bytes(stdin, memory, iovs_arr_cell))
wasi_try!(read_bytes(stdin, memory, &iovs_arr_cell))
} else {
return __WASI_EBADF;
}
Expand All @@ -918,7 +927,7 @@ pub fn fd_read(
Kind::File { handle, .. } => {
if let Some(handle) = handle {
handle.seek(std::io::SeekFrom::Start(offset as u64));
wasi_try!(read_bytes(handle, memory, iovs_arr_cell))
wasi_try!(read_bytes(handle, memory, &iovs_arr_cell))
} else {
return __WASI_EINVAL;
}
Expand All @@ -929,7 +938,7 @@ pub fn fd_read(
}
Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_read"),
Kind::Buffer { buffer } => {
wasi_try!(read_bytes(&buffer[offset..], memory, iovs_arr_cell))
wasi_try!(read_bytes(&buffer[offset..], memory, &iovs_arr_cell))
}
};

Expand Down Expand Up @@ -1267,7 +1276,7 @@ pub fn fd_write(
if let Some(ref mut stdout) =
wasi_try!(state.fs.stdout_mut().map_err(WasiFsError::into_wasi_err))
{
wasi_try!(write_bytes(stdout, memory, iovs_arr_cell))
wasi_try!(write_bytes(stdout, memory, &iovs_arr_cell))
} else {
return __WASI_EBADF;
}
Expand All @@ -1276,7 +1285,7 @@ pub fn fd_write(
if let Some(ref mut stderr) =
wasi_try!(state.fs.stderr_mut().map_err(WasiFsError::into_wasi_err))
{
wasi_try!(write_bytes(stderr, memory, iovs_arr_cell))
wasi_try!(write_bytes(stderr, memory, &iovs_arr_cell))
} else {
return __WASI_EBADF;
}
Expand All @@ -1296,7 +1305,7 @@ pub fn fd_write(
Kind::File { handle, .. } => {
if let Some(handle) = handle {
handle.seek(std::io::SeekFrom::Start(offset as u64));
wasi_try!(write_bytes(handle, memory, iovs_arr_cell))
wasi_try!(write_bytes(handle, memory, &iovs_arr_cell))
} else {
return __WASI_EINVAL;
}
Expand All @@ -1307,7 +1316,7 @@ pub fn fd_write(
}
Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_write"),
Kind::Buffer { buffer } => {
wasi_try!(write_bytes(&mut buffer[offset..], memory, iovs_arr_cell))
wasi_try!(write_bytes(&mut buffer[offset..], memory, &iovs_arr_cell))
}
};

Expand Down Expand Up @@ -2523,10 +2532,12 @@ pub fn random_get(env: &WasiEnv, buf: u32, buf_len: u32) -> __wasi_errno_t {
let res = getrandom::getrandom(&mut u8_buffer);
match res {
Ok(()) => {
memory
.view::<u8>()
.subarray(buf, buf + buf_len)
.copy_from(&u8_buffer);
unsafe {
memory
.view::<u8>()
.subarray(buf as usize..=(buf as usize + buf_len as usize))
.copy_from(&u8_buffer);
}
__WASI_ESUCCESS
}
Err(_) => __WASI_EIO,
Expand Down

0 comments on commit 1a8952e

Please sign in to comment.