Optimize some functions in the wiggle crate (#5566)

* wiggle: Inline some trivial functions

This commit marks a number of functions in wiggle as `#[inline]` as
they're otherwise trivial, mostly returning constants. This comes out of
some work I looked at recently with Andrew where some of these functions
showed up in profiles when they shouldn't.

* wiggle: Optimize the `GuestMemory` for shared memory

This commit implements a minor optimization to the `GuestMemory`
implementation for Wasmtime to skip most methods if a shared memory is
in play. Shared memories never get borrowed and this can be used to
internally skip some borrow-checker methods.

* wiggle: Optimize `GuestPtr::to_vec`

This commit replaces the safe implementation of `GuestPtr::to_vec` with
an unsafe implementation. The purpose of this is to speed up the
function when used with shared memory which otherwise performs a bunch
of atomic reads for types like `u8` which does validation-per-element
and isn't vectorizable. On a benchmark I was helping Andrew with this
sped up the host code enough to the point that guest code dwarfed the
execution time.

* Fix build
This commit is contained in:
Alex Crichton
2023-01-12 15:49:56 -06:00
committed by GitHub
parent d3e6b7bd2a
commit cbeec5ddb9
7 changed files with 68 additions and 7 deletions

View File

@@ -610,10 +610,22 @@ impl<'a, T> GuestPtr<'a, [T]> {
T: GuestTypeTransparent<'a> + Copy + 'a,
{
let guest_slice = self.as_unsafe_slice_mut()?;
let mut vec = Vec::with_capacity(guest_slice.ptr.len());
for offs in 0..guest_slice.ptr.len() {
let elem = self.get(offs as u32).expect("already validated the size");
vec.push(elem.read()?);
let len = guest_slice.ptr.len();
let mut vec = Vec::with_capacity(len);
// SAFETY: The `guest_slice` variable is already a valid pointer into
// the guest's memory, and it may or may not be a pointer into shared
// memory. We can't naively use `.to_vec(..)` which could introduce data
// races but all that needs to happen is to copy data into our local
// `vec` as all the data is `Copy` and transparent anyway. For this
// purpose the `ptr::copy` function should be sufficient for copying
// over all the data.
//
// TODO: audit that this use of `std::ptr::copy` is safe with shared
// memory (https://github.com/bytecodealliance/wasmtime/issues/4203)
unsafe {
std::ptr::copy(guest_slice.ptr.as_ptr().cast::<T>(), vec.as_mut_ptr(), len);
vec.set_len(len);
}
Ok(vec)
}