Skip to content

dev: Fuel const expr operator cost (#14215)

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 28 Sep 20:31
d8a0da6
* Charge const-expr operators the configured fuel cost

Operators inside constant expressions - global initializers, element and
data segment offsets, element segment expressions - were each charged a
hardcoded 1 fuel unit, so `Config::operator_cost` had no effect on any
instantiation-time work.

Constant expressions are stored as `ConstOp` rather than
`wasmparser::Operator`, so add a `const_op_cost` lookup alongside the
existing `cost` lookup and use it in `translate_const_expr`. Default costs
are unchanged: every `ConstOp` still costs 1 with the default table.

* Charge the configured Call cost for the synthesized start call

`module_start` synthesizes the call to a module's `(start ...)` function
and manually replicates the fuel accounting that `fuel_before_op` performs
for `Operator::Call`. That replica used a hardcoded 1 rather than the
configured cost, so the `Call` entry of `Config::operator_cost` did not
apply to the start call. Look the cost up from the table instead.

* Note the const-expr fuel change in RELEASES.md and tighten the tests

`Config::operator_cost` shipped in 48.0.0, so applying it to const-expr
operators and the synthesized start call changes the observable behavior
of released public API; note it under 49.0.0's `Changed` section.

Also pin a second cost-table entry in the const-expr test so a mis-wired
`ConstOp` match arm cannot pass, and document where the two flat
per-function entry charges in the start-call test come from.

* Reuse the operator cost lookup for const-expr operators

Translate a `ConstOp` back into the `wasmparser::Operator` it was parsed
from and charge it through the existing `OperatorCostStrategy::cost`,
rather than carrying a second lookup over the same table. That removes
the duplicate cost mapping and the default table that had to be kept in
sync with `default_operator_cost` by hand.

Only `ConstOp::RefNull` cannot reproduce its immediate, since
`TypeConvert::convert_heap_type` has no reverse; a placeholder heap type
stands in, which is fine because the cost lookup ignores immediates.

Also drop the test doc comments and assert the start-call test under the
default cost table as well as a custom one.

* Move the const-expr operator translation onto `ConstOp`

`ConstOp::to_operator` now lives next to `ConstOp::from_wasmparser`, and
`translate_const_expr` charges through `OperatorCostStrategy::cost`
directly, so `tunables.rs` no longer carries any const-expr specific
lookup.

Run both new tests under `#[wasmtime_test]` like the neighbouring cost
tests, with `extended_const` enabled for the `i32.add` initializer, and
link the release note to the PR.