前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「溯」@ Wasmer: 托管运行环境和可解释的程序状态

「溯」@ Wasmer: 托管运行环境和可解释的程序状态

作者头像
MikeLoveRust
发布2019-07-09 13:43:59
8640
发布2019-07-09 13:43:59
举报

昨天写完了 Wasmer PR #489 Su Engine 的实现。这个 PR 的核心功能是对 WebAssembly JIT 编译后代码运行状态的读取、解释和构造。以此为基础,我们可以实现一些有用的功能:

  • 切换编译器后端(Tier Switching)。Wasmer 有 Singlepass、Cranelift、LLVM 三个后端,其中,Singlepass 后端编译最快而运行最慢,LLVM 后端编译最慢而运行最快,Cranelift 编译运行速度均处中间水平。如果能够透明地由编译速度快的后端切换到运行效率高的后端,那么我们就可以同时支持“快速启动”和“高效执行”。
  • 调试(Backtrace、变量查看和修改)。成熟的语言和运行环境的必备特性之一。
  • 快照。我们可以像保存虚拟机快照一样随时保存 WebAssembly 程序的快照并在以后恢复。
  • 热迁移。WebAssembly 和 WASI 的沙盒化设计使得单程序级别的热迁移能够具有实际意义。
  • 垃圾回收(GC)。当然这需要等到 GC 被正式加入 WebAssembly 标准之后。

在此之前,除异常处理外,Wasmer 运行环境不会介入用户代码的执行。Su Engine 的设计目的是在几乎不引入性能损耗的前提下,为 WebAssembly 提供完整的托管(managed)运行环境。


「机器状态」的结构

刚才提到,Su Engine 的核心功能是读取、解释和构造 JIT 后代码的运行状态。这就涉及到目标架构机器状态和 WebAssembly 抽象机器状态之间的映射问题

这里以 x86-64 架构、Singlepass 编译后端为例。

以上是 Singlepass 后端所生成的代码在执行过程中单个函数的机器状态结构,包含栈帧和寄存器内容的语义信息。Su Engine 的实现中,每个关键位置(循环头部、函数头部、call 指令处、可能导致异常的位置)都对应一个机器状态结构的描述。

当 Wasmer 的信号处理函数接收到异常信号时,它会尝试获取当前指令地址所对应的机器状态结构,以这一结构为模板读取和解释异常上下文,然后以返回地址为初始指令地址重复这一过程,直到不存在与其对应的机器状态结构。“解释”的结果就是 WebAssembly 抽象机器状态,包含每个栈帧对应的 Function index、Opcode offset、Locals & stack values。

到此为止,我们实现了运行状态的读取和解释。以此为基础,Backtrace、查看变量等基本的调试功能就可以实现了。

要实现本文开头提到的其他功能,我们还需要另一个方向的映射 - 从抽象机器到目标机器的状态映射,也就是运行状态的“构造”。这基本上是“解释”的逆向过程,没有太多额外的复杂度。


与操作系统交互

Su Engine 需要与操作系统“合作”来高效地管理托管代码的执行过程。需要解决的主要问题包括:

  1. 接收到外部信号时,在某个特定的关键位置(循环头部、函数头部)暂停托管代码的执行
  2. 在信号处理函数中,获取异常上下文
  3. 切换到构造好的新机器状态,继续执行用户代码。

对于第 1 点的解决方案利用了内存保护机制。初始化 VM Context 时,Su Engine 会调用 mmap 分配一个 1 Page 大小的内存块作为“信号内存”。当收到外部中断信号(如 SIGINT)时,这个内存块将被设置为 PROT_NONE 而不可读写。编译后端生成代码时,会在上述关键位置处插入一个对这块信号内存的读访问。这样,外部中断信号最终将触发托管执行线程上的 SIGSEGV/SIGBUS 而被异常处理函数捕获。

第 2 点是利用信号处理函数 undocumented 的第三个 ucontext_t * 参数实现的。这个参数包含了异常的全部上下文信息。需要注意的是,ucontext_t 在 Linux 和 macOS 上的结构并不一致,这也是跨平台复杂性的来源之一。

第 3 点的实现基于类似协程的上下文切换机制,实现位于 lib/runtime-core/image-loading-{linux,macos}-x86-64.s 。

以上这些做法都是特定于 x86-64 Linux/macOS 的。当然,支持其他遵循 POSIX 系统接口和 System V ABI 的 x86-64 平台也应该比较容易。


Misc

Su Engine 中的 "Su" 对应中文“溯”,来源是 “溯洄从之”(《诗经·秦风·蒹葭》)。

演示视频:

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档