setjmp/longjmp 将如何在 WebAssembly 中实现?

How would setjmp/longjmp be implemented in WebAssembly?

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

鉴于它应该是一个 C 编译目标,它肯定可以实现 setjmplongjmp,但我不明白如何才能很好地完成它。这个结构在浪费中看起来如何?

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

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

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

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