You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Recognize table initialization code in start function and be able to devirtualize based on it #8869
Producers of wasm code prefer small binary size and may use table.fill instructions to initialize parts of a table (or other constructs, like a loop of increasing indices to initialize i31ref table) instead of emitting large element segments.
It would be nice if binaryen offered a flag (e.g. --trust-table-init-code or something like that) that would make it recognize this pattern and treat it as iff the regions were initialized in element sections and therefore be immutable and allow devirtualization / loads of the table to be folded away.
It could be an opt-in flag.
(In some sense an export of a table - e.g. in multi module scenarios - is in similar situation. One may want with a wasm-merge+wasm-opt+wasm-split the ability to devirtualize -- and would have an assumption that the exported table isn't used by 3rd party modules)
Is the table.fill using constant indexes and function reference? If so, and if nothing else appears before it in the start function, we could optimize here.
But another option might be to avoid table.fill until very late? As one of the last passes we could transform large elements into fills.
Is the table.fill using constant indexes and function reference?
Yes. Also the case where we initialize i31ref table with loop of increasing integers of known start/end.
If so, and if nothing else appears before it in the start function, we could optimize here.
There may be other effect-free things in the start functions, but we could re-order it to emit the table initialization code at the beginning if needed.
But another option might be to avoid table.fill until very late? As one of the last passes we could transform large elements into fills.
True, we could make dart2wasm emit only element section and have a new pass in binaryen that optimizes this the same way we do now in dart2wasm.
Would you prefer that?
(In general I like the idea of making dart2wasm do as good job as it can to emit small, fast code and then make wasm-opt do as good job as it can to make it's input as smaller/faster -- instead of making dart2wasm emit less optimized code in the hope that wasm-opt will optimize it.)
There may be other effect-free things in the start functions, but we could re-order it to emit the table initialization code at the beginning if needed.
Can we ensure this re-ordering even after merging? That is, if two modules have table init first in their start functions, and later other stuff, then merging will concatenate them and we no longer have that order.
Yes. Also the case where we initialize i31ref table with loop of increasing integers of known start/end.
Understanding loops may make this code complex, I worry.
(Aside from these two issues, I think we can do it the way you prefer, to let dart emit small code.)
Activity
kevmoo commentedon Jun 26, 2026
See #8866 – although my investigation led me to think it's not a good idea. 🤷
kripken commentedon Jun 26, 2026
Is the
table.fillusing constant indexes and function reference? If so, and if nothing else appears before it in the start function, we could optimize here.But another option might be to avoid
table.filluntil very late? As one of the last passes we could transform large elements into fills.mkustermann commentedon Jun 29, 2026
Yes. Also the case where we initialize i31ref table with loop of increasing integers of known start/end.
There may be other effect-free things in the start functions, but we could re-order it to emit the table initialization code at the beginning if needed.
True, we could make dart2wasm emit only element section and have a new pass in binaryen that optimizes this the same way we do now in dart2wasm.
Would you prefer that?
(In general I like the idea of making dart2wasm do as good job as it can to emit small, fast code and then make wasm-opt do as good job as it can to make it's input as smaller/faster -- instead of making dart2wasm emit less optimized code in the hope that wasm-opt will optimize it.)
kripken commentedon Jun 29, 2026
Can we ensure this re-ordering even after merging? That is, if two modules have table init first in their start functions, and later other stuff, then merging will concatenate them and we no longer have that order.
Understanding loops may make this code complex, I worry.
(Aside from these two issues, I think we can do it the way you prefer, to let dart emit small code.)