如何在WebAssembly中实现setjmp / longjmp?

时间:2017-05-30 13:01:25

标签: webassembly

我刚刚开始查看WebAssembly MVP,并注意到无法访问堆栈和堆栈指针,或者确实存在任何结构化异常处理支持(throw / catch)等。

鉴于它应该是一个C编译目标,肯定必须能够实现setjmplongjmp,但我无法理解如何做得很好。这个构造如何看待wast?

1 个答案:

答案 0 :(得分:6)

WebAssembly MVP不支持零成本异常处理。

C ++异常处理和setjmp / longjmp目前通过Emscripten实现,让每个try或“invoke”执行对JavaScript的调用,并继续使用WebAssembly的C ++代码。然后抛出一个JavaScript异常,它会展开堆栈并处理展开代码所在的“登陆板”(通常是析构函数调用和catch块)。这意味着每个延续都会收到一个布尔值:异常路径或常规路径。

这太贵了!如果LLVM无法证明函数调用无法抛出,那么其IR包含invoke指令,并且Emscripten依赖此函数来插入异常处理代码。 C ++中的默认设置是任何东西都可以抛出,所以如果你看一下LLVM IR,当你用异常进行编译时,整个地方都会有invoke

零成本exception handling is being worked on at the moment,因此这种情况最终应该解决。这将用于实施setjmp / longjmp。这可以启用setjmp / longjmp的所有已定义行为,即在不调用C ++析构函数的情况下展开堆栈。但是,它不允许未定义的行为情况向前跳转到已经解开的堆栈,有时用于实现协同程序。