【问题标题】:How would setjmp/longjmp be implemented in WebAssembly?如何在 WebAssembly 中实现 setjmp/longjmp?
【发布时间】:2017-05-30 13:01:25
【问题描述】:

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

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

【问题讨论】:

    标签: webassembly


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 啊哈!难怪我想不通!这远非理想,但公平地说,我认为最大的胜利是目前所有主要的浏览器供应商都已加入并交付或将很快交付 MVP。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    相关资源
    最近更新 更多