-
Notifications
You must be signed in to change notification settings - Fork 36
Conversation
proposals/Level-1.md
Outdated
Data types are extended to have a new `except_ref` type. The representation of | ||
an exception value is left to the host VM. | ||
Data types are extended to have a new `except_ref` type, that refers to an | ||
exception. The representation of an exception is left to the embedder. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"is left to the implementation"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
When an exception value is thrown, the host VM searches for nearest enclosing | ||
try block body that execution is in. That try block is called the _catching_ try | ||
block. | ||
When an exception value is thrown, the embedder searches for the nearest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"the embedder searches" - it's the Wasm VM. How about: "When an exception is thrown, the active try
block entered last is called the catching try block."
proposals/Level-1.md
Outdated
stack is popped back to the size the operand stack had when the try block was | ||
entered, and then the values of the caught exception value is pushed onto the | ||
stack. | ||
As expected, it is left to the embedder to define how WebAssembly exceptions are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to repeat what is already said on L193.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted
proposals/Level-1.md
Outdated
`else` instruction. The scope of the if_except block is from the `if_except` | ||
instruction to the corresponding `end` instruction. | ||
The `if_except` block begins with an `if_except` instruction, and | ||
has two instruction blocks, defined by the `then` and `else` instructions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There isn't really a then
instruction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we add one, to be symmetric with if
and else
instruction pair?
proposals/Level-1.md
Outdated
has two instruction blocks, defined by the `then` and `else` instructions | ||
like that of an `if` block. | ||
|
||
The `if_except` instruction queries of the exception on top of the stack, and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stray "of"
proposals/Level-1.md
Outdated
exception index defined in each module. | ||
For event indices imported/exported, unique event tags are created for each | ||
unique name imported/exported, and are aliased to the corresponding event index | ||
defined in each module. | ||
|
||
## Changes to the binary model |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
model -> format
proposals/Level-1.md
Outdated
### Data Types | ||
|
||
#### except_ref | ||
|
||
An exception reference points to an exception value. The size | ||
is fixed, but unknown in WebAssembly (the host defines the size in bytes). | ||
An exception reference points to an exception. The size is defined by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See earlier comment. I would drop any reference to size, given that it is not observable in any way.
In some places (example), this feature is called "zero-cost exceptions", referring to implementation strategies in which non-throwing code is optimized, at the expense of making throwing slow. This is useful for languages like Rust and C++. Is this proposal still intending to enable zero cost exceptions for WebAssembly? I'm aware that this is a performance consideration, rather than a semantic consideration. |
@sunfishcode - While we want to support many languages, I think the primary goal with this proposal is still to make sure C++ is well-supported. I agree that code that does not use throw or try/catch should not take a performance penalty just because the VM supports those exceptions. Do you have concerns that this proposal will be hard to implement without imposing a pervasive cost on all code? |
@eholk The term "zero cost" comes from the fact that in typical "zero cost" implementations, entering a Unifying exception handling with yield/resume seems counter to the assumptions of a "zero cost" model, because the whole point of a generator, for example, is to yield, often many times. It'd help me to understand this whole proposal if such considerations were documented. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly typo fixes
proposals/Level-1.md
Outdated
be garbage collected. | ||
Lastly, exception lifetimes may be maintained by the embedder, so that it can | ||
collect and reuse the memory used by exceptions. This implies that an embedder | ||
needs know where exceptions are stored, so that it can determine when an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
This also implies that the host VM must provide a garbage collector for | ||
exceptions. For host VMs that have garbage collection (such as JavaScript), | ||
This also implies that that embedders must provide a garbage collector for | ||
exceptions. For ebedders that have garbage collection (such as JavaScript), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
embedders
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
In general, an event handler allows one to process an event generated by a block | ||
of code. Events suspend the current execution and look for a corresponding event | ||
handler. If found, the corresponding event handler is run. Some event handlers | ||
my send values back to the suspended instruction, allowing the originating code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
event type. | ||
Each event has an `attribute` and a `type`. Currently, the attribute can only | ||
specify that the event is an exception. In the future, additional attribute | ||
values may be added when other events are added to WebAssemble. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WebAssembly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
In the first form, the instructions between the `if_except` and 'end' define the | ||
`then block`. In the second form, the instructions between the `if_except` and | ||
`else` define the `then block`, while the instructions between the `else` and | ||
the `end define the `else block`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing ` after end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
The conditional query of an exception checks the exception tag of exception on | ||
top of the stack. It succeeds only if the exception index of the instruction | ||
matches the corresponding exception tag. Once the query completes, the exception | ||
is poppod off the stack. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
popped
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
function calls until a corresponding, enclosing try block is found. It may also | ||
associate a stack trace that can be used to report uncaught exceptions. However, | ||
the details of this is left to the embedder, and WebAssembly does not have | ||
(direct) access to the stack trace. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
I thought the stack trace meant the call stack trace for debugging, but this says the operand stack traces. Are we not gonna have the call stack traces?
-
The previous version implied that we might add two-phase unwinding in the future. Is there any reason it was deleted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 - The stack trace is intended to be a call stack trace, and my read still states this.
- We may have two phase (for debugging), but we never stated that it would be mandatory. Dropped because that is an implementation detail and not a requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For what it's worth, stack traces are also an implementation detail since there is no way to access them from Wasm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the end of the last sentence (on direct access), since it is optional of the implementation.
proposals/Level-1.md
Outdated
`else` instruction. The scope of the if_except block is from the `if_except` | ||
instruction to the corresponding `end` instruction. | ||
The `if_except` block begins with an `if_except` instruction, and | ||
has two instruction blocks, defined by the `then` and `else` instructions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we add one, to be symmetric with if
and else
instruction pair?
proposals/Level-1.md
Outdated
|
||
| Field | Type | Description | | ||
|-------|------|-------------| | ||
| `index` | `varuitn32` | the index into the corresponding event index space | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
varuint32
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Can we add the syntactic sugar |
@sunfishcode : I voiced some similar concerns here: #42 The paper @rossberg linked https://www.microsoft.com/en-us/research/publication/implementing-algebraic-effects-c/ is very interesting because it has some actual timings you can expect from such resumable exceptions, which initially look pretty bad (compared to an implementation specialized purely for, say, generators), but it also shows a transformation that in a common case can avoid a stack-swap all-together, which would result in a very fast generator. I agree that it seems that exceptions and generators would have opposite requirements of what path should be fast. I am not sure if the transform mentioned in the paper can be applied commonly enough to bridge that gap. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed misspellings.
proposals/Level-1.md
Outdated
be garbage collected. | ||
Lastly, exception lifetimes may be maintained by the embedder, so that it can | ||
collect and reuse the memory used by exceptions. This implies that an embedder | ||
needs know where exceptions are stored, so that it can determine when an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
This also implies that the host VM must provide a garbage collector for | ||
exceptions. For host VMs that have garbage collection (such as JavaScript), | ||
This also implies that that embedders must provide a garbage collector for | ||
exceptions. For ebedders that have garbage collection (such as JavaScript), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
In general, an event handler allows one to process an event generated by a block | ||
of code. Events suspend the current execution and look for a corresponding event | ||
handler. If found, the corresponding event handler is run. Some event handlers | ||
my send values back to the suspended instruction, allowing the originating code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
event type. | ||
Each event has an `attribute` and a `type`. Currently, the attribute can only | ||
specify that the event is an exception. In the future, additional attribute | ||
values may be added when other events are added to WebAssemble. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
In the first form, the instructions between the `if_except` and 'end' define the | ||
`then block`. In the second form, the instructions between the `if_except` and | ||
`else` define the `then block`, while the instructions between the `else` and | ||
the `end define the `else block`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
The conditional query of an exception checks the exception tag of exception on | ||
top of the stack. It succeeds only if the exception index of the instruction | ||
matches the corresponding exception tag. Once the query completes, the exception | ||
is poppod off the stack. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
proposals/Level-1.md
Outdated
function calls until a corresponding, enclosing try block is found. It may also | ||
associate a stack trace that can be used to report uncaught exceptions. However, | ||
the details of this is left to the embedder, and WebAssembly does not have | ||
(direct) access to the stack trace. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 - The stack trace is intended to be a call stack trace, and my read still states this.
- We may have two phase (for debugging), but we never stated that it would be mandatory. Dropped because that is an implementation detail and not a requirement.
proposals/Level-1.md
Outdated
|
||
| Field | Type | Description | | ||
|-------|------|-------------| | ||
| `index` | `varuitn32` | the index into the corresponding event index space | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@sunfishcode @aardappel - @lukewagner voices similar concerns about the cost of throwing and catching exceptions in #19. Why don't we consolidate this discussion there and update the proposal as needed based on the results of the discussion? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm modulo nits
proposals/Level-1.md
Outdated
@@ -1,4 +1,4 @@ | |||
# Level 1 exception handling | |||
Level 1 exception handling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'd leave the #
so this is a heading.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
In the first form, the instructions between the `if_except` and 'end' define the | ||
`then block`. In the second form, the instructions between the `if_except` and | ||
`else` define the `then block`, while the instructions between the `else` and | ||
the `end` define the `else block`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sunfishcode pointed out that this optional else block complicates decoding. We should consider making this not optional (#54). This is an issue for another PR though.
proposals/Level-1.md
Outdated
found, it could terminate the thread at the point of the throw. This would | ||
allow better debugging capability, since the corresponding call stack is still | ||
there to query. | ||
When an exception is thrown, the runtime will pop the operand stack across |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably okay to be a little imprecise and just say "pop the stack across function calls" rather than specifying it's the operand stack.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant by "why only the operand stack traces and not call stack traces" here is this too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed "operand".
proposals/Level-1.md
Outdated
|
||
##### Exception section | ||
##### event section |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: capitalize "Event."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
* Add event handling * Clean up text * Clean up more * Fix order of arguments for if_except * Clean up description of event index/tag * Fix mispellings * Fix more nits
Change the exception handling proposal to use a more general notion of "events", so that it will be easier to generalize the proposal when yeild/resume events are added.