我刚刚开始研究 WebAssembly MVP,并注意到无法访问堆栈和堆栈指针,或者实际上没有任何结构化异常处理支持(抛出/捕获)等。
鉴于它应该是一个 C 编译目标,它肯定可以实现setjmp
and longjmp
,但我无法理解如何很好地做到这一点。这个结构在废物中看起来如何?
我刚刚开始研究 WebAssembly MVP,并注意到无法访问堆栈和堆栈指针,或者实际上没有任何结构化异常处理支持(抛出/捕获)等。
鉴于它应该是一个 C 编译目标,它肯定可以实现setjmp
and longjmp
,但我无法理解如何很好地做到这一点。这个结构在废物中看起来如何?
WebAssembly MVP 不支持零成本异常处理。
C++ 异常处理和setjmp
/longjmp
当前通过 Emscripten 实现,方法是让每个try
或“调用”执行对 JavaScript 的调用,并延续 WebAssembly 的 C++ 代码。然后 throw 会引发 JavaScript 异常,该异常会展开堆栈并处理展开代码所在的“着陆板”(通常是析构函数调用和catch
块)。这意味着每个延续都会收到一个布尔值:异常路径或常规路径。
这个超级贵!如果 LLVM 不能证明函数调用不能抛出,那么它的 IR 包含一条invoke
指令,Emscripten 依靠它来插入异常处理代码。C++ 中的默认设置是任何东西都可以抛出,所以如果你查看 LLVM IR,invoke
当你编译异常时到处都是 s。
目前正在开展零成本异常处理,因此这种情况最终应该会得到解决。这将用于实现setjmp
/ longjmp
。setjmp
这可以启用/的所有已定义行为longjmp
,即展开堆栈而不调用 C++ 析构函数。但是,它不允许未定义的行为情况,即向前跳转到已经展开的堆栈,该堆栈有时用于实现协程。