6

我刚刚开始研究 WebAssembly MVP,并注意到无法访问堆栈和堆栈指针,或者实际上没有任何结构化异常处理支持(抛出/捕获)等。

鉴于它应该是一个 C 编译目标,它肯定可以实现setjmpand longjmp,但我无法理解如何很好地做到这一点。这个结构在废物中看起来如何?

4

1 回答 1

7

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

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

这个超级贵!如果 LLVM 不能证明函数调用不能抛出,那么它的 IR 包含一条invoke指令,Emscripten 依靠它来插入异常处理代码。C++ 中的默认设置是任何东西都可以抛出,所以如果你查看 LLVM IR,invoke当你编译异常时到处都是 s。

目前正在开展零成本异常处理,因此这种情况最终应该会得到解决。这将用于实现setjmp/ longjmpsetjmp这可以启用/的所有已定义行为longjmp,即展开堆栈而不调用 C++ 析构函数。但是,它不允许未定义的行为情况,即向前跳转到已经展开的堆栈,该堆栈有时用于实现协程。

于 2017-05-30T14:52:05.197 回答