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

@@ -51,30 +51,50 @@ impl<'a> WasmtimeGuestMemory<'a> {
}
unsafe impl GuestMemory for WasmtimeGuestMemory<'_> {
#[inline]
fn base(&self) -> &[UnsafeCell<u8>] {
self.mem
}
// Note that this implementation has special cases for shared memory
// specifically because no regions of a shared memory can ever be borrowed.
// In the shared memory cases `shared_borrow` and `mut_borrow` are never
// called so that can be used to optimize the other methods by quickly
// checking a flag before calling the more expensive borrow-checker methods.
#[inline]
fn has_outstanding_borrows(&self) -> bool {
self.bc.has_outstanding_borrows()
!self.shared && self.bc.has_outstanding_borrows()
}
#[inline]
fn is_shared_borrowed(&self, r: Region) -> bool {
self.bc.is_shared_borrowed(r)
!self.shared && self.bc.is_shared_borrowed(r)
}
#[inline]
fn is_mut_borrowed(&self, r: Region) -> bool {
self.bc.is_mut_borrowed(r)
!self.shared && self.bc.is_mut_borrowed(r)
}
#[inline]
fn shared_borrow(&self, r: Region) -> Result<BorrowHandle, GuestError> {
debug_assert!(!self.shared);
self.bc.shared_borrow(r)
}
#[inline]
fn mut_borrow(&self, r: Region) -> Result<BorrowHandle, GuestError> {
debug_assert!(!self.shared);
self.bc.mut_borrow(r)
}
#[inline]
fn shared_unborrow(&self, h: BorrowHandle) {
debug_assert!(!self.shared);
self.bc.shared_unborrow(h)
}
#[inline]
fn mut_unborrow(&self, h: BorrowHandle) {
debug_assert!(!self.shared);
self.bc.mut_unborrow(h)
}
#[inline]
fn is_shared_memory(&self) -> bool {
self.shared
}