finite-wasm
finite-wasm copied to clipboard
Specification of the aggregate instructions clash with the intended behaviour
So today the spec for executing memory.fill
and such says something along the lines of:
- Let πΉ be the current frame.
- Assert: due to validation, πΉ.module.memaddrs[0] exists.
- Let
ma
be the memory address πΉ.module.memaddrs[0].- Assert: due to validation, π.mems[ma] exists.
- Let
mem
be the memory instance π.mems[ma].- Assert: due to validation, a value of value type
i32
is on the top of the stack.- Pop the value
i32.const π
from the stack.- Assert: due to validation, a value of value type
i32
is on the top of the stack.- Pop the value
val
from the stack.- Assert: due to validation, a value of value type
i32
is on the top of the stack.- Pop the value
i32.const π
from the stack.- If
π + π
is larger than the length ofmem.data
, then: a. Trap.- If
π = 0
, then: a. Return.- Push the value
i32.const π
to the stack.- Push the value val to the stack.
- Execute the instruction
i32.store8 {offset 0, align 0}
.- Assert: due to the earlier check against the memory size,
π + 1 < 2^32
.- Push the value
i32.const (π + 1)
to the stack.- Push the value val to the stack.
- Push the value
i32.const (π β 1)
to the stack.- Execute the instruction
memory.fill
.
The problem is that this operation reduces to multiple other plain instructions such as i32.store8
and memory.fill
. With how our specification is written, this will effectively cause memory.fill
to charge at least π
times the fee(i32.store8)
plus π
times the fee(memory.fill)
. In the implementation itself this will probably be a regular memset
and therefore run at different speeds depending on the π
.
The most straightforward option that came up as an idea is to, first, specify fee
as pattern matching on sequence of instructions and their reductions rather than executed instruction. That is, for n=3
it would see something like
(i32.const π) val (i32.const π) memory.fill
and we would be able to βpatternβ match this specific thing as a a memory.fill
of size π
and return a corresponding fee (while all of the i32.store8
s this reduces to internally would now be βfreeβ since calculating the fee for the whole aggregate does not recurse)