Skip to content

Commit 65df8c2

Browse files
committed
Simplify exception dispatch to branches
This proposes to use the idea suggested by WebAssembly#58 on using `br_on_exn` instead of `if_except`.
1 parent 530d2b9 commit 65df8c2

File tree

1 file changed

+55
-37
lines changed

1 file changed

+55
-37
lines changed

proposals/Exceptions.md

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,10 @@ Exception indices are used by:
128128
1. The `throw` instruction which creates a WebAssembly exception with the
129129
corresponding exception tag, and then throws it.
130130

131-
2. The `if_except` instruction queries an exception to see if the corresponding
132-
exception tag denoted by the exception index. If true it pushes the
133-
corresponding values of the exception onto the stack.
131+
2. The `br_on_exn` instruction queries an exception to see if the corresponding
132+
exception tag denoted by the exception index. If true it branches to the
133+
given label and pushes the corresponding values of the exception onto the
134+
stack.
134135

135136
### The exception reference data type
136137

@@ -215,39 +216,57 @@ exception on top of the stack is popped and then thrown.
215216

216217
### Exception data extraction
217218

218-
The `if_except` block begins with an `if_except` instruction, and has two
219-
instruction blocks,
220-
221-
That is, the forms of an if_except block is:
219+
The `br_on_exn` instruction is a conditional branch that checks the exception
220+
tag of an exception on top of the stack, in the form of:
222221

223222
```
224-
if_except block_type except_index
225-
Instruction*
226-
end
223+
br_on_exn label except_index
224+
```
225+
226+
The `br_on_exn` instruction checks the exception tag of an `except_ref` on top
227+
of the stack if it matches the given exception index. If it does, it branches
228+
out to the label referenced by the instruction (In the binary form, the label
229+
will be converted to a relative depth immediate, like other branch
230+
instructions), and while doing that, pops exception values from the `except_ref`
231+
and places them on top of the stack. In order to use these popped values, the
232+
block signature of the branch target has to match the exception types - because
233+
it receives the exception arguments as branch operands. If the exception tag
234+
does not match, the `except_ref` value remains on the stack. For example, when
235+
an `except_ref` contains an exception of type (i32 i64), the target block
236+
signature should be (i32 i64) as well, as in the following example:
227237

228-
if_except block_type except_index
229-
Instruction*
230-
else
231-
Instruction*
238+
```
239+
block $l (result i32 i64)
240+
...
241+
;; except_ref $e is on the stack at this point
242+
br_on_exn $l ;; branch to $l with $e's arguments
243+
...
232244
end
233245
```
234246

235-
In the first form, the instructions between the `if_except` and 'end' define the
236-
`then block`. In the second form, the instructions between the `if_except` and
237-
`else` define the `then block`, while the instructions between the `else` and
238-
the `end` define the `else block`.
239-
240-
The conditional query of an exception checks the exception tag of exception on
241-
top of the stack. It succeeds only if the exception index of the instruction
242-
matches the corresponding exception tag. Once the query completes, the exception
243-
is popped off the stack.
247+
This can now be used to construct handler switches in the same way `br_table`
248+
is used to construct regular switch:
244249

245-
If the query succeeds the values (associated with the popped exception) are
246-
extracted and pushed onto the stack, and control transfers to the instructions
247-
in the then block.
250+
```
251+
block $end
252+
block $l1
253+
...
254+
block $lN
255+
br_on_exn $l1
256+
...
257+
br_on_exn $lN
258+
rethrow
259+
end $lN
260+
;; handler for $eN here
261+
br $end
262+
...
263+
end $l1
264+
;; handler for $e1
265+
end $end
266+
```
248267

249-
If the query fails, it either enters the else block, or transfer control to the
250-
end of the if_except block if there is no else block.
268+
If the query fails, the control flow falls through, and no values are pushed
269+
onto the stack.
251270

252271
### Stack traces
253272

@@ -269,15 +288,14 @@ The following rules are added to *instructions*:
269288
try resulttype instruction* catch instruction* end |
270289
throw except_index |
271290
rethrow |
272-
if_except resulttype except_index then instruction* end |
273-
if_except resulttype except_index then instruction* else instruction* end
291+
br_on_exn label except_index
274292
```
275293

276-
Like the `block`, `loop`, and `if` instructions, the `try` and `if_except`
277-
instructions are *structured* control flow instructions, and can be labeled.
278-
This allows branch instructions to exit try and `if_except` blocks.
294+
Like the `block`, `loop`, and `if` instructions, the `try` instruction is
295+
*structured* control flow instruction, and can be labeled. This allows branch
296+
instructions to exit try blocks.
279297

280-
The `except_index` of the `throw` and `if_except` instructions defines the
298+
The `except_index` of the `throw` and `br_on_exn` instructions defines the
281299
exception (and hence, exception tag) to create/extract from. See [exception
282300
index space](#exception-index-space) for further clarification of exception
283301
tags.
@@ -442,7 +460,7 @@ throws, and rethrows as follows:
442460
| `catch` | `0x07` | | begins the catch block of the try block |
443461
| `throw` | `0x08` | index : `varint32` | Creates an exception defined by the exception `index`and then throws it |
444462
| `rethrow` | `0x09` | | Pops the `except_ref` on top of the stack and throws it |
445-
| `if_except` | `0x0a` | index : `varuint32`, sig : `block_type` | Begin exception data extraction if exception on stack was created using the corresponding exception `index` |
463+
| `br_on_exn` | `0x0a` | relative_depth : `varuint32`, index : `varuint32` | Branches to the given label and extracts data within `except_ref` on top of stack if it was created using the corresponding exception `index` |
446464

447-
The *sig* fields of `block`, `if`, `try` and `if_except` operators are block
448-
signatures which describe their use of the operand stack.
465+
The *sig* fields of `block`, `if`, and `try` operators are block signatures
466+
which describe their use of the operand stack.

0 commit comments

Comments
 (0)