WebAssembly / WebAssembly/binaryen
Optimization issue where allocation is not eliminated
@stevenfontanella is already working on this.
Since Apr 22, 2026.
- Dominant language
- WebAssembly
- Stars
- 8.6k
- Forks
- 885
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 69
Description
Dart uses iterators pervasively, especially over lists (e.g. for (final value in list) { ... }). The iterable (list) provides a get:iterator method. The iterator then has a iterator.moveNext() and iterator.current. If we know which list type it is we'd like to avoid the iterator overhead.
We have been doing inlining on the dart2wasm side to avoid that. Now I'm experimenting with adjusting our inliner and have noticed an issue in binaryen:
- if dart2wasm does more inlining the iterator allocation disppears after binaryen optimizations
- if dart2wasm does less inlining, binaryen does the inlining for us, but the iterator allocation stays
Example: The dart code looks like this:
final a = A();
main() {
a.doIt();
a.doIt();
}
class A {
final a1 = <int>[];
final a2 = <double>[];
final a3 = <String>[];
void doIt() {
for (final x in a1) {
print(x);
}
for (final x in a2) {
print(x);
}
for (final x in a3) {
print(x);
}
}
}
Here we want to avoid the allocation of the iterator (a _GrowableListIterator wasm struct).
See allocation_elimination_issue.tar.gz. Unpacking with tar xvzf allocation_elimination_issue.tar.gz will give
# Dart2wasm does the inlining
test.before.wasm
test.before.wasm.wat
# The test.before.wasm optimized via -Os -Os -Os
test.before.opt.wasm
test.before.opt.wasm.wat
# Dart2wasm does less inlining, binaryen does the rest (it inlines `call $"_GrowableListIterator.current= implicit setter"`)
test.after.wasm
test.after.wasm.wat
# The test.after.wasm optimized via -Os -Os -Os
test.after.opt.wasm
test.after.opt.wasm.wat
Here we can see that (func $A.doit ...) is much larger if we leave the inlining to binaryen, as it doesn't eliminiate the _GrowableListIterator struct allocations.
(Optimization via wasm-opt --enable-gc --enable-reference-types --enable-multivalue --enable-exception-handling --enable-nontrapping-float-to-int --enable-sign-ext --enable-bulk-memory --enable-threads --enable-simd '--no-inline=*<noInline>*' --traps-never-happen -g -Os -Os -Os test.before.wasm -o test.before.opt.wasm and same for test.after.wasm -> test.after.opt.wasm)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.