-
Notifications
You must be signed in to change notification settings - Fork 694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Terminator operators that imply "end" #778
Comments
There seems to be some merit exploring this. The type validation of dead code does appear to be a problem when relating the wasm code back to a presentation format, and this might help. Would this mean that This might help reduce code size when a block fall through needs to unwind the values stack and end the block with a branch, so it can omit the Then would |
Correction:
Perhaps E.g. |
Yes, though with the block signature change, they could be the same:
Yes, since the general
Vs with an
I think given the frequency of |
This proposal makes sense to me. Along with block signatures, this proposal would give us a concrete stack state at every instruction, with no special states or modes. Even if special states or modes are simple today, they require have the potential to interact with future features, and they require extra testing. One detail: removing
(and any of the |
A notable feature of this proposal is that it eliminates the awkward zone between an unconditional branch and the subsequent end while still permitting unreachable code. A producer that knows it may emit unreachable code can start a new |
Good point, so unreachable code can still be emitted like:
But would this unreachable code be type validated or not? |
Yes, it you add explicit signature to the blocks. e.g.:
I've been rewriting WAVM to support the binary format + stack machine semantics, and am currently targeting a hypothetical version that has both #765 and this implicit terminator proposal. I'm happy to say that eliminates quite a bit of complexity in the validator since, as @sunfishcode pointed out, it eliminates the possibility of code where the stack is in an unknown state. It moves a little of that complexity to assembling a WAST file, but overall I'm happy with it. |
@AndrewScheidecker Out of curiosity, does you experimental design have anything to say on the semantics of the block end? See the discussion in WebAssembly/spec#326 Do you see a need for the block |
In my prototype,
There isn't a good way to replace the final |
@AndrewScheidecker Was Perhaps two signatures too, unless the common case is a void result. A A btw: might there me merit in
|
I was under the impression it was going to change to one label, but it looks like it hasn't been merged yet (#710), so perhaps it will keep both labels. If the branch target stack isn't 1:1 with the control structure stack (e.g. the terminating operator for the loop control structure will implicitly pop two branch targets), then it does seem like
I agree that it would be nice, but it needs to be exposed through WAST for it to be useful, so my test just uses signatures with no parameters and an inferred return type. |
But the |
I converted WAVM to do what I believe the current standard is (unreachable code is allowed between an unconditional branch and the Part of the change is to use distinct opcodes for The zipped size savings were about .5%; that's comparing against a WASM that already didn't have any unreachable code that would be disallowed by this change, so it only comes from two changes: the |
An alternative thought: target index 0 goes to the next instruction. In the case of |
@Kardax hmm, to me it makes more sense to eliminate the default case, so |
@qwertie Assuming that AngryBots13.wasm is a real-world example, target-0-is-next-instruction would save 4194* bytes, but eliminating the default case would only save 1398* as this particular file has no default 0, necessitating the immediate next instruction to be a All of the options discussed in this issue will save bytes, though, so I think if the binary format is not yet frozen, one of these approaches should be implemented. (*) Branches targeting what used to be level 127 but is now 128 will grow by 1 byte; I'm not accounting for this currently, but such deep block stacks should be uncommon. |
I have no data in front of me, but thinking about C switches, in the majority of them, I believe omitting Edit: I just realized I don't know what you meant by "this file has no default 0" so I did not actually understand what you said. But I'm Canadian, so, sorry. |
@qwertie AngryBots13.wasm has no instances of |
It's too late for this. |
WebAssembly has several operators that imply that any code following them until the next
end
orelse
operator will never be executed:ret
,br
,br_table
,unreachable
.I propose that these operators act as implicit
end
/else
operators. This would imply that they may only occur at the end of a control flow block. Theend
operator would still be useful as a special-casebr
operator that targets a fixed depth of 0.This also makes it clear that
else
can be eliminated, and that anif
operator just needs to be followed by two terminator instructions.I believe this simplifies code generation, since you don't need to worry about the stack having the right type going into an unreachable
end
operator. I believe it also simplifies the spec and validation, since it completely avoids the question of how to handle code between these operators and the nextend
.The text was updated successfully, but these errors were encountered: