Skip to content

Commit 61f24aa

Browse files
authored
winch: emit fuel updates before throwing exceptions (#14297)
1 parent f61dd31 commit 61f24aa

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

tests/all/fuel.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,58 @@ fn custom_operator_cost(config: &mut Config) -> Result<()> {
694694
Ok(())
695695
}
696696

697+
#[wasmtime_test(wasm_features(exceptions, reference_types))]
698+
#[cfg_attr(miri, ignore)]
699+
fn exceptions_with_fuel(config: &mut Config) -> Result<()> {
700+
config.consume_fuel(true);
701+
let engine = Engine::new(config)?;
702+
let module = Module::new(
703+
&engine,
704+
r#"
705+
(module
706+
(tag $e (param i32))
707+
708+
(func (export "throw") (param i32) (result i32)
709+
(block $catch (result i32)
710+
(try_table (result i32) (catch $e $catch)
711+
local.get 0
712+
if
713+
i32.const 42
714+
throw $e
715+
end
716+
i32.const 7)))
717+
718+
(func (export "throw_ref") (result i32)
719+
(block $catch (result i32)
720+
(try_table (result i32) (catch $e $catch)
721+
(block $rethrow (result i32 exnref)
722+
(try_table (result i32 exnref) (catch_ref $e $rethrow)
723+
i32.const 42
724+
throw $e))
725+
throw_ref))))
726+
"#,
727+
)?;
728+
let mut store = Store::new(&engine, ());
729+
store.set_fuel(100)?;
730+
let instance = Instance::new(&mut store, &module, &[])?;
731+
732+
let throw = instance.get_typed_func::<i32, i32>(&mut store, "throw")?;
733+
for (condition, result, consumed) in [(0, 7, 5), (1, 42, 6)] {
734+
store.set_fuel(100)?;
735+
assert_eq!(throw.call(&mut store, condition)?, result);
736+
// Function entry, try_table, local.get, if, and i32.const each
737+
// consume one fuel unit, as does throw when the branch is taken.
738+
assert_eq!(store.get_fuel()?, 100 - consumed);
739+
}
740+
741+
let throw_ref = instance.get_typed_func::<(), i32>(&mut store, "throw_ref")?;
742+
store.set_fuel(100)?;
743+
assert_eq!(throw_ref.call(&mut store, ())?, 42);
744+
// Function entry, two try_tables, i32.const, throw, and throw_ref.
745+
assert_eq!(store.get_fuel()?, 94);
746+
Ok(())
747+
}
748+
697749
#[wasmtime_test(wasm_features(bulk_memory, reference_types, gc, function_references))]
698750
#[cfg_attr(miri, ignore)]
699751
fn custom_variable_operator_cost(config: &mut Config) -> Result<()> {

winch/codegen/src/codegen/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2384,7 +2384,9 @@ where
23842384
| Operator::CallIndirect { .. }
23852385
| Operator::Call { .. }
23862386
| Operator::ReturnCall { .. }
2387-
| Operator::ReturnCallIndirect { .. } => self.emit_fuel_increment(),
2387+
| Operator::ReturnCallIndirect { .. }
2388+
| Operator::Throw { .. }
2389+
| Operator::ThrowRef => self.emit_fuel_increment(),
23882390
_ => Ok(()),
23892391
}
23902392
}

0 commit comments

Comments
 (0)