Should producers/consumers assume throwing is "rare" and, if so, can the spec note this?
This is certainly the basic assumption for C++ but not for many other languages. The underlying question is whether engines can assume they can use the classic "zero-cost" EH strategy without tanking on performance of some language that throws all the time. AFAICS, if one has to assume throwing/catching can be a hot path, it'd be preferable to use either an extra 'throwing' return value (with branches on every callsite) or a setjmp/longjmp-like strategy, which produce a general slowdown in the non-throwing case.
Given that:
- the reason to add EH to wasm is to allow compilers/runtimes to achieve better performance than they could otherwise in wasm-without-EH,
- the zero-cost strategy is something only the engine can do (at least in the short- to medium-term),
- with multi-return, a compiler/toolchain could implement a pretty-fast non-zero-cost EH strategy in wasm-without-EH,
I think we should non-normatively state this assumption in the spec so engines can predictably provide the performance of the zero-cost strategy.
I agree that zero-cost exceptions are the long-term goal. I didn't want to add it to the document because I thought it was a distraction from the primary concern of getting the concept in WebAsembly.
Partly, this issue is just a question for the entire wasm cg because it'd be good to see if everyone is on the same page here.
Assuming we are: for the spec/proposal, we probably don't have to go into any implementation details (like "zero-cost"). Rather, we could just say, in a non-normative note in the spec and an informative para in the proposal, that exceptions are assumed to be used for exceptional control flow and thus engines may choose impl strategies that bias towards the best non-exceptional performance at the cost of exceptional performance.
It would be good to quantify this: how close are we perf-wise and size-wise to:
- Exceptions off on native platforms
- Exceptions on but never thrown ** Exceptions on and throws
Related discussions have cropped up at https://github.com/WebAssembly/exception-handling/pull/49#issuecomment-368889883 and https://github.com/WebAssembly/exception-handling/pull/42#discussion_r167716629.
On the one hand, I think the spec should avoid imposing requirements on implementations strategies. On the other hand, I'm not sure we want to get into a world where some engines are tuned for code that throws exceptions often (like Java) and others are tuned for code where throwing exceptions is extremely rare (like Rust). Ideally any Wasm code would run with similar performance characteristics on all engines.
I think a sufficiently advanced implementation would get the best of both worlds anyway, e.g. use the "multiple return values" approach when the catching code is close to the throwing code, and stack unwinding otherwise.