Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for ResourceLimiter API #737

Merged
merged 23 commits into from
Jul 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
71fa9d4
Sketch of support for ResourceLimiter API
graydon Jun 29, 2023
c4d66ee
Address review comments.
graydon Jun 30, 2023
8e0da23
Handle the 3 separate ResourceLimiter response types more correctly.
graydon Jun 30, 2023
6afb5ef
Fix typo in existing error message.
graydon Jun 30, 2023
610fae7
Add StoreLimits, StoreLimitsBuilder and docs from wasmtime.
graydon Jun 30, 2023
5f0a428
Fix unused-variable warnings.
graydon Jun 30, 2023
15ab197
Conditionalize ResourceLimiter on cfg(feature="std")
graydon Jun 30, 2023
bcfb80b
Add ResourceLimiter test and fix bugs it uncovered.
graydon Jun 30, 2023
09aaf8d
Avoid redundant limit and size storage in previous wasmtime-like design.
graydon Jun 30, 2023
8eeea83
Thread an ever-so-smaller &mut ResourceLimiterRef into the Executor
graydon Jun 30, 2023
7dc0251
Support no_std differently (import alloc::boxed::Box)
graydon Jul 1, 2023
071df16
Avoid storing &ResourceLimiterRef in Executor (maybe breaks SROA?)
graydon Jul 1, 2023
32da9ff
Fix no_std a little harder.
graydon Jul 1, 2023
9f68c38
Restore TableError::GrowOutOfBounds fields
graydon Jul 3, 2023
14b3c07
Remove now-redundant pub(crate)
graydon Jul 3, 2023
11a0739
Remove unnecessary cfg guard on alloc::boxed::Box
graydon Jul 3, 2023
8436a1c
Address clippy warnings
graydon Jul 3, 2023
1b07fa4
Fix doc reference.
graydon Jul 3, 2023
c005b8f
Some cleanups as requested in review.
graydon Jul 4, 2023
831ec46
Fix wasmi_core doc-link to wasmi, deps do not go that way.
graydon Jul 4, 2023
61d8e45
Fix s/State/Store/ doc typo
graydon Jul 4, 2023
a11d8c1
Add docs on Store::limiter
graydon Jul 4, 2023
25b4e7a
Fix new nightly clippy nit
graydon Jul 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crates/core/src/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,13 @@ pub enum TrapCode {
/// internal bytecode so that fuel is consumed for each executed instruction.
/// This is useful to deterministically halt or yield a WebAssembly execution.
OutOfFuel,

/// This trap is raised when a growth operation was attempted and an
/// installed `wasmi::ResourceLimiter` returned `Err(...)` from the
/// associated `table_growing` or `memory_growing` method, indicating a
/// desire on the part of the embedder to trap the interpreter rather than
/// merely fail the growth operation.
GrowthOperationLimited,
}

impl TrapCode {
Expand All @@ -305,6 +312,7 @@ impl TrapCode {
Self::StackOverflow => "call stack exhausted",
Self::BadSignature => "indirect call type mismatch",
Self::OutOfFuel => "all fuel consumed by WebAssembly",
Self::GrowthOperationLimited => "growth operation limited",
}
}
}
Expand Down
37 changes: 24 additions & 13 deletions crates/wasmi/src/engine/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use crate::{
ValueStack,
},
func::FuncEntity,
store::ResourceLimiterRef,
table::TableEntity,
FuelConsumptionMode,
Func,
Expand Down Expand Up @@ -92,15 +93,17 @@ pub enum ReturnOutcome {
///
/// If the Wasm execution traps.
#[inline(never)]
pub fn execute_wasm<'engine>(
ctx: &mut StoreInner,
pub fn execute_wasm<'ctx, 'engine>(
ctx: &'ctx mut StoreInner,
cache: &'engine mut InstanceCache,
value_stack: &'engine mut ValueStack,
call_stack: &'engine mut CallStack,
code_map: &'engine CodeMap,
const_pool: ConstPoolView<'engine>,
resource_limiter: &'ctx mut ResourceLimiterRef<'ctx>,
) -> Result<WasmOutcome, TrapCode> {
Executor::new(ctx, cache, value_stack, call_stack, code_map, const_pool).execute()
Executor::new(ctx, cache, value_stack, call_stack, code_map, const_pool)
.execute(resource_limiter)
}

/// The function signature of Wasm load operations.
Expand Down Expand Up @@ -213,7 +216,10 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {

/// Executes the function frame until it returns or traps.
#[inline(always)]
fn execute(mut self) -> Result<WasmOutcome, TrapCode> {
fn execute(
mut self,
resource_limiter: &'ctx mut ResourceLimiterRef<'ctx>,
) -> Result<WasmOutcome, TrapCode> {
use Instruction as Instr;
loop {
match *self.ip.get() {
Expand Down Expand Up @@ -280,13 +286,13 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {
Instr::I64Store16(offset) => self.visit_i64_store_16(offset)?,
Instr::I64Store32(offset) => self.visit_i64_store_32(offset)?,
Instr::MemorySize => self.visit_memory_size(),
Instr::MemoryGrow => self.visit_memory_grow()?,
Instr::MemoryGrow => self.visit_memory_grow(&mut *resource_limiter)?,
Instr::MemoryFill => self.visit_memory_fill()?,
Instr::MemoryCopy => self.visit_memory_copy()?,
Instr::MemoryInit(segment) => self.visit_memory_init(segment)?,
Instr::DataDrop(segment) => self.visit_data_drop(segment),
Instr::TableSize(table) => self.visit_table_size(table),
Instr::TableGrow(table) => self.visit_table_grow(table)?,
Instr::TableGrow(table) => self.visit_table_grow(table, &mut *resource_limiter)?,
Instr::TableFill(table) => self.visit_table_fill(table)?,
Instr::TableGet(table) => self.visit_table_get(table)?,
Instr::TableSet(table) => self.visit_table_set(table)?,
Expand Down Expand Up @@ -1077,7 +1083,10 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {
}

#[inline(always)]
fn visit_memory_grow(&mut self) -> Result<(), TrapCode> {
fn visit_memory_grow(
&mut self,
resource_limiter: &mut ResourceLimiterRef<'ctx>,
) -> Result<(), TrapCode> {
let delta: u32 = self.sp.pop_as();
let delta = match Pages::new(delta) {
Some(pages) => pages,
Expand All @@ -1097,9 +1106,8 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {
let new_pages = this
.ctx
.resolve_memory_mut(memory)
.grow(delta)
.map(u32::from)
.map_err(|_| EntityGrowError::InvalidGrow)?;
.grow(delta, resource_limiter)
.map(u32::from)?;
// The `memory.grow` operation might have invalidated the cached
// linear memory so we need to reset it in order for the cache to
// reload in case it is used again.
Expand Down Expand Up @@ -1210,7 +1218,11 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {
}

#[inline(always)]
fn visit_table_grow(&mut self, table_index: TableIdx) -> Result<(), TrapCode> {
fn visit_table_grow(
&mut self,
table_index: TableIdx,
resource_limiter: &mut ResourceLimiterRef<'ctx>,
) -> Result<(), TrapCode> {
let (init, delta) = self.sp.pop2();
let delta: u32 = delta.into();
let result = self.consume_fuel_with(
Expand All @@ -1219,8 +1231,7 @@ impl<'ctx, 'engine> Executor<'ctx, 'engine> {
let table = this.cache.get_table(this.ctx, table_index);
this.ctx
.resolve_table_mut(&table)
.grow_untyped(delta, init)
.map_err(|_| EntityGrowError::InvalidGrow)
.grow_untyped(delta, init, resource_limiter)
},
);
let result = match result {
Expand Down
4 changes: 3 additions & 1 deletion crates/wasmi/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,18 +793,20 @@ impl<'engine> EngineExecutor<'engine> {
code.into()
}

let store_inner = &mut ctx.store.inner;
let (store_inner, mut resource_limiter) = ctx.store.store_inner_and_resource_limiter_ref();
let value_stack = &mut self.stack.values;
let call_stack = &mut self.stack.frames;
let code_map = &self.res.code_map;
let const_pool = self.res.const_pool.view();

execute_wasm(
store_inner,
cache,
value_stack,
call_stack,
code_map,
const_pool,
&mut resource_limiter,
)
.map_err(make_trap)
}
Expand Down
4 changes: 1 addition & 3 deletions crates/wasmi/src/func/typed_func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,7 @@ impl<Results> Default for CallResultsTuple<Results> {
impl<Results> Copy for CallResultsTuple<Results> {}
impl<Results> Clone for CallResultsTuple<Results> {
fn clone(&self) -> Self {
Self {
_marker: PhantomData,
}
*self
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/wasmi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ mod externref;
mod func;
mod global;
mod instance;
mod limits;
mod linker;
mod memory;
mod module;
Expand Down Expand Up @@ -145,6 +146,7 @@ pub use self::{
},
global::{Global, GlobalType, Mutability},
instance::{Export, ExportsIter, Extern, ExternType, Instance},
limits::{ResourceLimiter, StoreLimits, StoreLimitsBuilder},
linker::Linker,
memory::{Memory, MemoryType},
module::{
Expand Down
Loading