mirror of
https://github.com/extism/extism.git
synced 2026-01-08 21:38:13 -05:00
feat: add benchmarking, optimize bounds checking in the kernel (#505)
- Adds benchmarking, run with `cargo bench` or `cargo criterion` - Adds `MemoryRoot::pointer_in_bounds_fast` to do less precise bounds checking in loads/stores --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: zshipko <zshipko@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cargo build --release --target wasm32-unknown-unknown --package extism-runtime-kernel --bin extism-runtime
|
||||
export CARGO_FLAGS=""
|
||||
|
||||
while getopts d flag
|
||||
do
|
||||
case "${flag}" in
|
||||
d)
|
||||
echo "Disabled bounds-checking";
|
||||
export CARGO_FLAGS="--no-default-features";;
|
||||
*)
|
||||
echo "usage $0 [-d]"
|
||||
echo "\t-d: build with bounds checking disabled"
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
|
||||
cargo build --package extism-runtime-kernel --bin extism-runtime --release --target wasm32-unknown-unknown $CARGO_FLAGS
|
||||
cp target/wasm32-unknown-unknown/release/extism-runtime.wasm .
|
||||
wasm-strip extism-runtime.wasm
|
||||
mv extism-runtime.wasm ../runtime/src/extism-runtime.wasm
|
||||
|
||||
@@ -184,11 +184,21 @@ impl MemoryRoot {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[allow(unused)]
|
||||
fn pointer_in_bounds(&self, p: Pointer) -> bool {
|
||||
let start_ptr = self.blocks.as_ptr() as Pointer;
|
||||
p >= start_ptr && p < start_ptr + self.length.load(Ordering::Acquire) as Pointer
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[allow(unused)]
|
||||
fn pointer_in_bounds_fast(p: Pointer) -> bool {
|
||||
// Similar to `pointer_in_bounds` but less accurate on the upper bound. This uses the total memory size,
|
||||
// instead of checking `MemoryRoot::length`
|
||||
let end = core::arch::wasm32::memory_size(0) << 16;
|
||||
p >= core::mem::size_of::<Self>() as Pointer && p <= end as Pointer
|
||||
}
|
||||
|
||||
// Find a block that is free to use, this can be a new block or an existing freed block. The `self_position` argument
|
||||
// is used to avoid loading the allocators position more than once when performing an allocation.
|
||||
unsafe fn find_free_block(
|
||||
@@ -290,10 +300,7 @@ impl MemoryRoot {
|
||||
|
||||
/// Finds the block at an offset in memory
|
||||
pub unsafe fn find_block(&mut self, offs: Pointer) -> Option<&mut MemoryBlock> {
|
||||
let blocks_start = self.blocks.as_ptr() as Pointer;
|
||||
if offs < blocks_start
|
||||
|| offs >= blocks_start + self.length.load(Ordering::Acquire) as Pointer
|
||||
{
|
||||
if !Self::pointer_in_bounds_fast(offs) {
|
||||
return None;
|
||||
}
|
||||
let ptr = offs - core::mem::size_of::<MemoryBlock>() as u64;
|
||||
@@ -372,7 +379,7 @@ pub unsafe fn extism_length(p: Pointer) -> Length {
|
||||
#[no_mangle]
|
||||
pub unsafe fn extism_load_u8(p: Pointer) -> u8 {
|
||||
#[cfg(feature = "bounds-checking")]
|
||||
if !MemoryRoot::new().pointer_in_bounds(p) {
|
||||
if !MemoryRoot::pointer_in_bounds_fast(p) {
|
||||
return 0;
|
||||
}
|
||||
*(p as *mut u8)
|
||||
@@ -382,7 +389,7 @@ pub unsafe fn extism_load_u8(p: Pointer) -> u8 {
|
||||
#[no_mangle]
|
||||
pub unsafe fn extism_load_u64(p: Pointer) -> u64 {
|
||||
#[cfg(feature = "bounds-checking")]
|
||||
if !MemoryRoot::new().pointer_in_bounds(p + core::mem::size_of::<u64>() as Pointer - 1) {
|
||||
if !MemoryRoot::pointer_in_bounds_fast(p + core::mem::size_of::<u64>() as u64 - 1) {
|
||||
return 0;
|
||||
}
|
||||
*(p as *mut u64)
|
||||
@@ -412,7 +419,7 @@ pub unsafe fn extism_input_load_u64(p: Pointer) -> u64 {
|
||||
#[no_mangle]
|
||||
pub unsafe fn extism_store_u8(p: Pointer, x: u8) {
|
||||
#[cfg(feature = "bounds-checking")]
|
||||
if !MemoryRoot::new().pointer_in_bounds(p) {
|
||||
if !MemoryRoot::pointer_in_bounds_fast(p) {
|
||||
return;
|
||||
}
|
||||
*(p as *mut u8) = x;
|
||||
@@ -422,7 +429,7 @@ pub unsafe fn extism_store_u8(p: Pointer, x: u8) {
|
||||
#[no_mangle]
|
||||
pub unsafe fn extism_store_u64(p: Pointer, x: u64) {
|
||||
#[cfg(feature = "bounds-checking")]
|
||||
if !MemoryRoot::new().pointer_in_bounds(p) {
|
||||
if !MemoryRoot::pointer_in_bounds_fast(p + core::mem::size_of::<u64>() as u64 - 1) {
|
||||
return;
|
||||
}
|
||||
*(p as *mut u64) = x;
|
||||
|
||||
Reference in New Issue
Block a user