Uh oh!
There was an error while loading. Please reload this page.
[Wasm GC] Ignore unreachable sets for purposes of non-nullable locals - #5665
[Wasm GC] Ignore unreachable sets for purposes of non-nullable locals#5665kripken wants to merge 7 commits into
Conversation
kripken
commented
Apr 14, 2023
It turns out this is tricky. If we land this PR, then any pass that does a refinalize will need to fix up non-nullable locals, beceause refinalization can propagate unreachability - and with this PR, unreachability affects non-nullable local validation. In practice , that means adding non-nullable fixups to 24 more passes (!) (all those that don't do it now, but do perform a refinalize). That's so many passes that probably we would want to just constantly run non-nullable fixups after every pass and not bother with |
tlively
commented
Apr 14, 2023
Another workaround would be to treat these local.sets specially in the binary writer and emit them even though we otherwise wouldn't. Another fix would be in the spec/v8, where we could consider all locals to be initialized in unreachable code. |
tlively
commented
Apr 14, 2023
Filed WebAssembly/function-references#98 to discuss a spec change. |
kripken
commented
Apr 17, 2023
Unfortunately, I found this wouldn't be simple, as atm we stop at the first block etc. child that is unreachable. So to do this, we'd need to continue onward to check for sets, which would add complexity and overhead. |
tlively
commented
Apr 17, 2023
What about the solution of continuing to skip emitting things even beyond the end of blocks, as long as those blocks are unnamed? |
kripken
commented
Apr 17, 2023
That doesn't seem simple. It would affect multiple functions, as e.g. Lines 237 to 241 in 5679e3b It might be worth trying though, I'm just saying it's not obvious to me that it will work or work easily. (OTOH, just running non-nullable local fixups, or just running dce before binary emitting, would definitely work and be very simple - but slow us down.) |
tlively
commented
Apr 17, 2023
This would all be much easier if we could separate iteration from other logic using generators built on C++20 coroutines :'( |
kripken
commented
Apr 18, 2023
I had the idea to notice in ReFinalize when we turn a set unreachable. That is rare, so doing more work in that case would be fine. And it's a change in one place (ReFinalize) and not in multiple passes. That works ok (with some fallout in (module
(func$2
(local$3 (refarray))
(drop
(block (result nullref)
(unreachable)
(local.set$3
(ref.as_non_null
(ref.null none)
)
)
(ref.null none)
)
)
(drop
(local.get$3)
)
)
)That won't validate in v8 but it does work in Binaryen. Noticing that in ReFinalize is not simple and would, I think, add overhead (we'd need to track when we turn any child of anything unreachable, and see if there's a set after it). |
DCE at the end avoids issues with non-nullable local operations in unreachable code, which is still being discussed. This PR avoids fuzzer errors for now, but we should revert it when we have a proper fix. See * #5599 * #5665 * WebAssembly/function-references#98
kripken
commented
Apr 25, 2023
As of #5677 we have a fuzzer workaround here, and nothing else seems urgent. Closing, and we'll see how the spec and other discussions go around this topic. |
See #5665#5599, this is an existing issue and we have a workaround for it using --dce, but it does not always work. I seem to be seeing this in higher frequency since landing recent fuzzer improvements, so ignore it. There is some risk of us missing real bugs here (that we validate and V8 does not), but this is a validation error which is not as serious as a difference in behavior. And this is a long-standing issue that hasn't bitten us yet.
DCE at the end avoids issues with non-nullable local operations in unreachable code, which is still being discussed. This PR avoids fuzzer errors for now, but we should revert it when we have a proper fix. See * WebAssembly#5599 * WebAssembly#5665 * WebAssembly/function-references#98
…Assembly#6337) See WebAssembly#5665WebAssembly#5599, this is an existing issue and we have a workaround for it using --dce, but it does not always work. I seem to be seeing this in higher frequency since landing recent fuzzer improvements, so ignore it. There is some risk of us missing real bugs here (that we validate and V8 does not), but this is a validation error which is not as serious as a difference in behavior. And this is a long-standing issue that hasn't bitten us yet.
As pointed out by @tlively in #5599, we don't emit unreachable code in the binary
format, which means such sets can't help gets validate.
Fixes#5599