From 65df8c23fa3b9c8c22a4fb6525884a7b61ef0d35 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Fri, 30 Nov 2018 19:12:32 -0800 Subject: [PATCH 1/2] Simplify exception dispatch to branches This proposes to use the idea suggested by #58 on using `br_on_exn` instead of `if_except`. --- proposals/Exceptions.md | 92 ++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/proposals/Exceptions.md b/proposals/Exceptions.md index 28d9fb3e..8f1282ef 100644 --- a/proposals/Exceptions.md +++ b/proposals/Exceptions.md @@ -128,9 +128,10 @@ Exception indices are used by: 1. The `throw` instruction which creates a WebAssembly exception with the corresponding exception tag, and then throws it. -2. The `if_except` instruction queries an exception to see if the corresponding - exception tag denoted by the exception index. If true it pushes the - corresponding values of the exception onto the stack. +2. The `br_on_exn` instruction queries an exception to see if the corresponding + exception tag denoted by the exception index. If true it branches to the + given label and pushes the corresponding values of the exception onto the + stack. ### The exception reference data type @@ -215,39 +216,57 @@ exception on top of the stack is popped and then thrown. ### Exception data extraction -The `if_except` block begins with an `if_except` instruction, and has two -instruction blocks, - -That is, the forms of an if_except block is: +The `br_on_exn` instruction is a conditional branch that checks the exception +tag of an exception on top of the stack, in the form of: ``` -if_except block_type except_index - Instruction* -end +br_on_exn label except_index +``` + +The `br_on_exn` instruction checks the exception tag of an `except_ref` on top +of the stack if it matches the given exception index. If it does, it branches +out to the label referenced by the instruction (In the binary form, the label +will be converted to a relative depth immediate, like other branch +instructions), and while doing that, pops exception values from the `except_ref` +and places them on top of the stack. In order to use these popped values, the +block signature of the branch target has to match the exception types - because +it receives the exception arguments as branch operands. If the exception tag +does not match, the `except_ref` value remains on the stack. For example, when +an `except_ref` contains an exception of type (i32 i64), the target block +signature should be (i32 i64) as well, as in the following example: -if_except block_type except_index - Instruction* -else - Instruction* +``` +block $l (result i32 i64) + ... + ;; except_ref $e is on the stack at this point + br_on_exn $l ;; branch to $l with $e's arguments + ... end ``` -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`. - -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 popped off the stack. +This can now be used to construct handler switches in the same way `br_table` +is used to construct regular switch: -If the query succeeds the values (associated with the popped exception) are -extracted and pushed onto the stack, and control transfers to the instructions -in the then block. +``` +block $end + block $l1 + ... + block $lN + br_on_exn $l1 + ... + br_on_exn $lN + rethrow + end $lN + ;; handler for $eN here + br $end + ... + end $l1 + ;; handler for $e1 +end $end +``` -If the query fails, it either enters the else block, or transfer control to the -end of the if_except block if there is no else block. +If the query fails, the control flow falls through, and no values are pushed +onto the stack. ### Stack traces @@ -269,15 +288,14 @@ The following rules are added to *instructions*: try resulttype instruction* catch instruction* end | throw except_index | rethrow | - if_except resulttype except_index then instruction* end | - if_except resulttype except_index then instruction* else instruction* end + br_on_exn label except_index ``` -Like the `block`, `loop`, and `if` instructions, the `try` and `if_except` -instructions are *structured* control flow instructions, and can be labeled. -This allows branch instructions to exit try and `if_except` blocks. +Like the `block`, `loop`, and `if` instructions, the `try` instruction is +*structured* control flow instruction, and can be labeled. This allows branch +instructions to exit try blocks. -The `except_index` of the `throw` and `if_except` instructions defines the +The `except_index` of the `throw` and `br_on_exn` instructions defines the exception (and hence, exception tag) to create/extract from. See [exception index space](#exception-index-space) for further clarification of exception tags. @@ -442,7 +460,7 @@ throws, and rethrows as follows: | `catch` | `0x07` | | begins the catch block of the try block | | `throw` | `0x08` | index : `varint32` | Creates an exception defined by the exception `index`and then throws it | | `rethrow` | `0x09` | | Pops the `except_ref` on top of the stack and throws it | -| `if_except` | `0x0a` | index : `varuint32`, sig : `block_type` | Begin exception data extraction if exception on stack was created using the corresponding exception `index` | +| `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` | -The *sig* fields of `block`, `if`, `try` and `if_except` operators are block -signatures which describe their use of the operand stack. +The *sig* fields of `block`, `if`, and `try` operators are block signatures +which describe their use of the operand stack. From 89b9039f6781d07b85e067d87bfd743052cd2b17 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Mon, 3 Dec 2018 15:50:27 -0800 Subject: [PATCH 2/2] Address comments --- proposals/Exceptions.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/proposals/Exceptions.md b/proposals/Exceptions.md index 8f1282ef..28b46dd7 100644 --- a/proposals/Exceptions.md +++ b/proposals/Exceptions.md @@ -128,10 +128,10 @@ Exception indices are used by: 1. The `throw` instruction which creates a WebAssembly exception with the corresponding exception tag, and then throws it. -2. The `br_on_exn` instruction queries an exception to see if the corresponding - exception tag denoted by the exception index. If true it branches to the - given label and pushes the corresponding values of the exception onto the - stack. +2. The `br_on_exn` instruction queries an exception to see if it matches the + corresponding exception tag denoted by the exception index. If true it + branches to the given label and pushes the corresponding argument values of + the exception onto the stack. ### The exception reference data type @@ -227,13 +227,14 @@ The `br_on_exn` instruction checks the exception tag of an `except_ref` on top of the stack if it matches the given exception index. If it does, it branches out to the label referenced by the instruction (In the binary form, the label will be converted to a relative depth immediate, like other branch -instructions), and while doing that, pops exception values from the `except_ref` -and places them on top of the stack. In order to use these popped values, the -block signature of the branch target has to match the exception types - because -it receives the exception arguments as branch operands. If the exception tag -does not match, the `except_ref` value remains on the stack. For example, when -an `except_ref` contains an exception of type (i32 i64), the target block -signature should be (i32 i64) as well, as in the following example: +instructions), and while doing that, pops the `except_ref` value from the stack +and instead pushes the exception's argument values on top of the stack. In order +to use these popped values, the block signature of the branch target has to +match the exception types - because it receives the exception arguments as +branch operands. If the exception tag does not match, the `except_ref` value +remains on the stack. For example, when an `except_ref` contains an exception of +type (i32 i64), the target block signature should be (i32 i64) as well, as in +the following example: ``` block $l (result i32 i64)