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 }}
This repository was archived by the owner on Nov 3, 2021. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 3, 2021. It is now read-only.
This proposal introduces a typed select instruction, which takes reference types and also a return type. The return type is written as a vector of valtype. Currently only the vector of length 1 is accepted in the v8 validation. I guess the reason it is a vector is for the multivalue proposal, right?
Is there a reason this has a different representation from that of block, loop, and if type when there are multiple types? blocktype for the multivalue proposal says it is extended to have a type index in the presence of multi values. This will be applied to other instructions such as loops and ifs. Wouldn't it be better for select to be consistent?
See this comment for the rationale behind the format. I honestly don't know what a block type (as introduced by multi-values) would mean for select, since the instruction does not have independent argument and result types, like blocks have.
Could we enforce in validation that the input types be empty and the output types be whatever would be in the vector today? Or maybe inputs and outputs should be the same. Or maybe the signature should be the full type of the select, including the condition.
Anyway, we can enforce whatever signatures make the most sense. The rationale for doing this is the same as the rationale for disallowing inline multivalue block types, that is deduplication of types and compactness of encoding.
We could, but it would be odd -- for example, then we'd need to artificially introduce the params into the text format, too.
In terms of compactness it wouldn't actually be a win here: most of the cases where it would be a win (single argument) are covered with even less bytes by the existing unannotated select already. And for multi-parameter cases, going through a func type can easily be a net loss rather than a win if it is a one-off use.
And of course, compactness isn't even remotely as relevant for this instruction as it is for blocks, since its frequency of use will almost certainly be in the noise.
(FWIW, I believe we discussed and concluded all this at the A Coruna meeting.)
Ah, that's a somewhat different story. For events, non-empty result types are reserved and will actually be meaningful with future extensions for resumable exceptions / effect handlers / coroutines / stack switching (I plan to present more concrete ideas at the Feb meeting). So that's more like the situation with block signatures.
Reacted by Thomas Lively and Paul Schoenfelder
Reacted by Kadie 𒂗𒃶𒌌𒀭𒈾 𒀭𒈹 (Kadie Enheduanna Inanna)
@rossberg Do you have any notes or anything about what you have in mind for coroutines/stack switching? I'm most interested in whether or not the coroutine primitives would be designed around stackful coroutines, or stackless coroutines. Presumably the presence of stack switching primitives would allow for the former, so I guess even if the coroutine primitives are stackless, having the stack switching primitives would be enough to do what I need.
If you recall we had some discussion on an issue earlier this year about coroutines/continuations, but there was no immediate plans to support anything like that, other than the possibility that resumable exceptions might provide a way to implement a form of delimited continuations; and the lack of appropriate stack primitives meant neither coroutines nor continuations could be implemented from the ground up either. If that is something that will change in the the coming year, that would be fantastic! I definitely would be interested in helping move that work forward, if I can be of assistance.
@bitwalker, nothing I can currently point to, sorry. But yes, the goal here is to provide a "stack switching" primitive, so in C++ terminology, it would be "stackful" coroutines. AFAICS, "stackless" pseudo coroutines aren't all that interesting for Wasm, since a producer can implement them themselves via a fairly local program transformation.
The more interesting distinction is between symmetric and asymmetric coroutines, and this would be the latter.
Roughly, the idea is a new reference type cont $ft of continuations (a.k.a. stacks), where $ft is a function type, along with respective instructions cont.new, cont.yield, cont.resume, and a few more. Unlike more conventional coroutines, the continuation type allows passing values back and forth between yield and resume points. But this has to be typed properly in Wasm, and that's where event declarations come in: yield generates an event with a certain type and passes along its arguments (like throw). It can only be resumed by passing back the event's results (adopting ideas from effect handlers). Like exceptions and their exn values, events are captured as first-class values of a type evt, so that resumption can happen even after the parent has returned.
Activity
rossberg commentedon Nov 20, 2019
See this comment for the rationale behind the format. I honestly don't know what a block type (as introduced by multi-values) would mean for select, since the instruction does not have independent argument and result types, like blocks have.
[Interpreter] Implement rest of the instructions (#64)
tlively commentedon Nov 20, 2019
Could we enforce in validation that the input types be empty and the output types be whatever would be in the vector today? Or maybe inputs and outputs should be the same. Or maybe the signature should be the full type of the select, including the condition.
Anyway, we can enforce whatever signatures make the most sense. The rationale for doing this is the same as the rationale for disallowing inline multivalue block types, that is deduplication of types and compactness of encoding.
rossberg commentedon Nov 21, 2019
We could, but it would be odd -- for example, then we'd need to artificially introduce the params into the text format, too.
In terms of compactness it wouldn't actually be a win here: most of the cases where it would be a win (single argument) are covered with even less bytes by the existing unannotated
selectalready. And for multi-parameter cases, going through a func type can easily be a net loss rather than a win if it is a one-off use.And of course, compactness isn't even remotely as relevant for this instruction as it is for blocks, since its frequency of use will almost certainly be in the noise.
(FWIW, I believe we discussed and concluded all this at the A Coruna meeting.)
tlively commentedon Nov 21, 2019
Ok, it sounds like there are good reasons for this and I don’t want to needlessly rehash old discussions. Thanks for your explanations!
tlively commentedon Nov 22, 2019
@rossberg I just realized there is another place where we constrain signature types. In the exceptions proposal the event signatures must have empty result types: https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md#event-handling. Does that make enforcing a similar constraint for select sufficiently less odd that we should reconsider it?
rossberg commentedon Nov 23, 2019
Ah, that's a somewhat different story. For events, non-empty result types are reserved and will actually be meaningful with future extensions for resumable exceptions / effect handlers / coroutines / stack switching (I plan to present more concrete ideas at the Feb meeting). So that's more like the situation with block signatures.
bitwalker commentedon Nov 23, 2019
@rossberg Do you have any notes or anything about what you have in mind for coroutines/stack switching? I'm most interested in whether or not the coroutine primitives would be designed around stackful coroutines, or stackless coroutines. Presumably the presence of stack switching primitives would allow for the former, so I guess even if the coroutine primitives are stackless, having the stack switching primitives would be enough to do what I need.
If you recall we had some discussion on an issue earlier this year about coroutines/continuations, but there was no immediate plans to support anything like that, other than the possibility that resumable exceptions might provide a way to implement a form of delimited continuations; and the lack of appropriate stack primitives meant neither coroutines nor continuations could be implemented from the ground up either. If that is something that will change in the the coming year, that would be fantastic! I definitely would be interested in helping move that work forward, if I can be of assistance.
rossberg commentedon Nov 24, 2019
@bitwalker, nothing I can currently point to, sorry. But yes, the goal here is to provide a "stack switching" primitive, so in C++ terminology, it would be "stackful" coroutines. AFAICS, "stackless" pseudo coroutines aren't all that interesting for Wasm, since a producer can implement them themselves via a fairly local program transformation.
The more interesting distinction is between symmetric and asymmetric coroutines, and this would be the latter.
Roughly, the idea is a new reference type
cont $ftof continuations (a.k.a. stacks), where$ftis a function type, along with respective instructionscont.new,cont.yield,cont.resume, and a few more. Unlike more conventional coroutines, the continuation type allows passing values back and forth between yield and resume points. But this has to be typed properly in Wasm, and that's where event declarations come in: yield generates an event with a certain type and passes along its arguments (likethrow). It can only be resumed by passing back the event's results (adopting ideas from effect handlers). Like exceptions and theirexnvalues, events are captured as first-class values of a typeevt, so that resumption can happen even after the parent has returned.