-
Notifications
You must be signed in to change notification settings - Fork 472
Incomplete implementation of explicit-drop #326
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
Comments
On Thu, Sep 1, 2016 at 5:51 PM, Dan Gohman [email protected] wrote:
|
At the moment, it's the only mention of the explicit-drop requirement in the design repo, and the wording is clear, even if it does need to to be updated for the new stack-machine terminology. |
On 1 September 2016 at 17:57, titzer [email protected] wrote:
Obviously, this was meant up to unwinds, otherwise the sentence wouldn't
Right, this sentence obviously makes no sense anymore in the stack machine All values still have to be consumed "explicitly" either as operand or by
|
This change wasn't discussed in the stack-machine documents, and isn't mentioned explicitly in the stack PR. It's an interesting decision, and I'm seeking rationale material, regardless of the outcome. The argument against considering an unconditional branch to be a use of excess values in its block is that the values aren't actually being used. Explicit drops help simple consumers avoid allocating resources up front for values that have no actual uses, and if there's a motivation for an enforced rule to encourage this in some contexts, then there's a motivation for it in all contexts (even if there are also motivations for other considerations). Would you mind stating the argument in favor? Alternatively, would it make sense to drop (;-)) the explicit-drop rule altogether and just let |
Agree with @sunfishcode -- explicit |
It's not really a separate change or decision, it's just a consequence of the stack machine, which naturally is more lenient than structured expressions. Branches always unwind in Wasm, and I don't have a good idea on what grounds this corner case should be ruled out. Or what the typing rules to achieve that would be. It would be introducing a special case. As for implementations, breaks have to unwind in general, and operationally there is nothing special about this case in particular. All consumers will need to implement the mechanics anyway. Your argument seems to be that it helps to discover some trivial cases of redundant code, but why would simple consumers care about identifying redundant code, and why are these corner cases more relevant than others? Concretely, how's their effort any different from the following example, which is obviously legal?
|
@drom The discussion is getting rather confusing. There is an 'explict-drop' rule versus an 'explict drops as optional'. Which one of these do you agree with? The unwinding rules will make it much more efficient to code up patterns using
If performance of a simple compiler is a key design goal then we need to explore that, need to consider register pressure, need to consider |
Why would it be a special case? We already have a place in the language where validation requires that there not be excess elements on the stack, at an Or from the opposite direction: why does
The explicit-drop rules are concerned with dead definitions, which are not always caused by redundant code.
In my original example, the i32.const's value has no users anywhere in the program. In this example here, the i32.const's value has a use in the program -- the drop (which we've defined to be a use). |
On Fri, Sep 2, 2016 at 7:10 PM, Dan Gohman [email protected] wrote:
|
I think it would help if this were the case, certainly good for |
@sunfishcode, how do you envision distinguishing the example in question,
from a case like
that has to remain valid? Without requiring implementations to type-check Moreover, branches are just one case of unwinding. If you replace Or from the opposite direction: why does end not perform an unwind, and
Because our blocks are (scoped) labels, not branches. They are not intended That was the point of the explicit drop change anyway, which you were |
@rossberg-chromium With the change discussed in WebAssembly/design#778 the unconditional branch would end the block, so
If blocks were just scoped labels then there would be no restriction on popping values past their boundary, so I don't see that as a useful or familiar interpretation. We don't need the
It was not the only point. There were other related changes. We had a deep values stack due to the 'every operation is an expression' design, so lots of values remaining on the values stack and still potentially live as seen by a single pass compiler. Also because values were AST nodes, even void nodes took a slot. This problem has been large addressed, without A design that prohibits excess values on the stack at a block exit is not compatible with There is little remaining technical case for the A plausible design is within sight. Lets have block ends unwind too which clears excess values, have blocks return the number of values in their block signature, adopt the changes in WebAssembly/design#778 and adopt |
On 5 September 2016 at 23:07, JSStats [email protected] wrote:
Any design ruling out dead code has no precedent in other stack VMs, and If blocks were just scoped labels then there would be no restriction on
It's a purely static MVP restriction (remnant of the expression language) A design that prohibits excess values on the stack at a block exit is not
It is perfectly compatible with a "deep" pick if you lift the restriction I A plausible design is within sight. Lets have block ends unwind too which
Oh, if that's all... ;) |
The discussion in WebAssembly/design#778 does not rule out dead code - I thought it did too initially, but see the clarification from @sunfishcode What it does seem to do is allow type validation of all code, so we don't have some blobs of code that are not type valid. Could you please take a closer look. We have been going over this part of the design again and again, it's been tough, and I do see some light in this area. Do you understand my proposal, do you see any problems with it? Examples are good, so here's one to illustrate the problem for
The above would be invalid because there are values left on the values stack that can not be dropped. It would help me understand your proposal if you could illustrate how it solves this? |
On 6 September 2016 at 08:52, JSStats [email protected] wrote:
Yes, but only by requiring each such compiler to wrap every branch into its Examples are good, so here's one to illustrate the problem for pick:
I see, interesting point. However, to me this example rather shows that
No magic block needed. |
@rossberg-chromium Scoped Your proposal in stack machine code:
There is one benefit in using this style. The live range on the let values might end sooner. But this can be done by adding regular blocks anyway. For example:
Are there any benefits of your proposal that I have missed? |
@rossberg-chromium Your explanations here have been helpful for me to understand your perspective; thanks. I agree that It is fascinating that there have been numerous ideas floating around for how unreachable code could be handled:
and the example you show here is easy to understand what I'm talking about in all of the above, and hard to understand in the following:
ECMA 335 (the CLR), I.12.4 Control flow, "The evaluation stack shall be empty after the return value is popped by a ret instruction." |
This enables running all the SIMD tests (in test/core/simd) whenever we do `make test`.
Refactor casts in interpreter
some runtimes implement tag matching as the equality of tag indexes. (cf. bytecodealliance/wasm-micro-runtime#3109) i believe it's a wrong interpreteation of the spec. this test case ensures a failure on such implementations.
As stated in #694, the intention of the explicit-drop rules is that:
The stack branch of ml-proto currently accepts this:
The current design states:
This is using pre-stack-machine terminology, but in those terms, the example above shows a code sequence in which an expression appears in a block-like sequence of expressions, is not the last expression in the block, and yet does yield a value.
The text was updated successfully, but these errors were encountered: