Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Simplify exception dispatch to branches #58

Closed
rossberg opened this issue Jun 1, 2018 · 5 comments
Closed

Simplify exception dispatch to branches #58

rossberg opened this issue Jun 1, 2018 · 5 comments

Comments

@rossberg
Copy link
Member

rossberg commented Jun 1, 2018

The current if_except for handling exceptions is a structured instruction and as such quite complex. For example, embodying blocks, it has to deal with block signatures, labels, etc.

In the context of working on the GC proposal, where a similar construct is needed for downcasts, I realised that we probably don't want to introduce a zoo of block constructs. And it turns out that with the multi-value proposal we can simplify all these by replacing them with simple branches.

For the exception proposal, this would mean that instead of the structured if_except construct, we simply have a new branch of the form

br_on_exn <labelidx> <exnidx>

which checks whether the exception package on the top of the stack matches the exception denoted by <exnidx>, and if so, branches to <labelidx>. The trick, however, is that the block signature of the branch target has to be compatible with the exception's tag type -- because it receives the exception arguments as branch operands. If the exception does not match, it remains on the stack.

For example:

(exception $e i32 i64)
...
block $l (result i32 i64)
  ...
  try
    (i32.const 1)
    (i64.const 2)
    (throw $e)
  catch
    (br_on_exn $l $e)  ;; branch to $l with $e's arguments
    (rethrow)  ;; ignore other exceptions
  end
  ...
end
;; (i32.const 1) (i64.const 2) are now on the stack

This can now be used to construct handler switches in the same way br_table is used to construct regular switch:

block $end
  block $l1
    ...
      block $lN
        (br_on_exn $l1 $e1)
        ...
        (br_on_exn $lN $eN)
        (rethrow)
      end $lN
      ;; handler for $eN here
      (br $end)
    ...
  end $l1
  ;; handler for $e1
end $end

I think this is a simpler primitive and makes better reuse of existing instructions. (The try construct remains unchanged.) WDYT?

@rossberg
Copy link
Member Author

rossberg commented Jun 1, 2018

And complementary to the semantics I gave here, these are the rules for the alternative construct, replacing handle in the other rules. As you can hopefully see, it is simpler.

Syntax

instr ::= ... | br_on_exn <labelidx> <exnidx>

Typing

C.exn(x) = C.label(l)
----------------------------------------------
C |- br_on_exn l x : [exn] -> [exn]

Reduction

F; (caught a v*) br_on_exn l x  -->  F; v* (br l)
  iff F.module.exn(x) = a

F; (caught a v*) br_on_exn l x  -->  F; (caught a v*)
  iff F.module.exn(x) =/= a

@binji
Copy link
Member

binji commented Jun 4, 2018

Interesting. I also was a bit concerned about making everything a block, so it's nice that this avoids that. The structure it requires seems a bit more awkward, but I suppose it's only as awkward as the br_table structure typically is.

@eholk
Copy link
Contributor

eholk commented Jun 4, 2018

My first impression is that I like this proposal. It's nice that we can just add an instruction rather than a new block type.

I'm curious how this would affect the tools. I got the sense that if_except was kind of awkward for the tools to use. Maybe this br_on_exn would actually be easier to use? Or maybe it's just awkward in a different way.

@aheejin
Copy link
Member

aheejin commented Jun 5, 2018

Actually, I'm currently doing the prototype implementation based on the first proposal with one modification, which is rethrow instruction targeting a label suggested by @rossberg. Like two months ago, we decided to change the internal LLVM IR representation to use the Windows-EH style scoped IR, so targeting the previous proposal now seem a lot more feasible. But I haven't finished the implementation yet, and using a first-class exception type may help reduce the code size, so I don't want to close the door on any of the proposals yet.

Before changing to this, I tried to implement if_except, and it was a bit awkward but I could make it work. But anyway, now I'm prototyping based on the first proposal, so for now I took out the if_except implementation.

aheejin added a commit to aheejin/exception-handling that referenced this issue Dec 1, 2018
This proposes to use the idea suggested by WebAssembly#58 instead of `if_except`.
aheejin added a commit to aheejin/exception-handling that referenced this issue Dec 1, 2018
This proposes to use the idea suggested by WebAssembly#58 on using `br_on_exn`
instead of `if_except`.
aheejin added a commit that referenced this issue Dec 3, 2018
This proposes to use the idea suggested by #58 on using `br_on_exn`
instead of `if_except`.
@aheejin
Copy link
Member

aheejin commented Oct 20, 2019

Closed by #71.

@aheejin aheejin closed this as completed Oct 20, 2019
ioannad pushed a commit to ioannad/exception-handling that referenced this issue Jun 6, 2020
ioannad pushed a commit to ioannad/exception-handling that referenced this issue Feb 23, 2021
This proposes to use the idea suggested by WebAssembly#58 on using `br_on_exn`
instead of `if_except`.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants