Rust 在底层会引发恐慌,并且在.NET 中实现它们

主要观点:作者正在开发 Rust 到.NET 的编译器rustc_codegen_clr,需用.NET API 实现 Rust 特性,本文是关于 Rust 恐慌、展开及在.NET 中实现的系列文章第一篇,介绍了编译器工作原理、恐慌与展开的区别、编译器级展开、清理块、优化清理块的困难、空清理块、优化异常处理句柄等内容,还提及项目周年、参与 GSoC 及感谢相关人员等。
关键信息:

  • rustc_codegen_clr将 Rust 的 MIR 转化为.NET 的 CIL,使 Rust 能轻松调用.NET 函数和创建对象,目标是实现 Rust 与 C#/F#的无缝互操作。
  • 恐慌是 Rust 语言的特性,用于表示程序逻辑错误,展开是恐慌的一种实现,指栈展开并丢弃栈上数据,清理块用于在展开时丢弃栈帧中的数据。
  • 优化清理块困难,Rust 编译为.NET 时在一些关键区域有大幅减速,复杂迭代器性能问题突出,异常处理句柄生成大量字节码影响.NET JIT 优化。
  • 简单的优化清理块方法是检查 CIL 是否有可观察到的副作用,若只有赋值、跳转和重新抛出则可删除。
  • rustc_codegen_clr项目一周年,参与了 Rust GSoC,感谢导师 Jack Huey、Rust GSoC 组织者 Jakub Beránek 及 wider Rust 项目成员的帮助。
    重要细节:
  • 函数由一系列基本块组成,基本块由语句和终止器构成,只有终止器能改变函数的控制流,这简化了展开和清理栈帧。
  • 清理块在正常执行时不调用,仅在展开时用于丢弃数据,其概念类似 C#中的finallyusing,但只在展开时调用。
  • 为解决变量可能未初始化的问题,编译器引入了隐藏的丢弃标志变量。
  • MIR 优化基于通用函数,利用 Rust 特定信息进行更快的优化,但不能对所有类型进行优化。
  • 空清理块是因为某些类型(如i64)不需要丢弃,drop_glue可能为None导致无实际操作。
    -.NET JIT 使用启发式算法估计优化的价值,根据基本块数量等因素决定是否内联函数,过多的异常处理句柄会影响内联。
  • 作者最初用复杂方法检测无用清理块,后采用更简单保守的方法,即检查 CIL 是否有可观察到的副作用来删除。
阅读 12
0 条评论