Geo*_*uer 13 .net c# theory cil tail-call-optimization
所以我之前已经阅读了很多次,技术上.NET 确实支持尾调用优化(TCO),因为它有操作码,只有C#不生成它.
我不确定为什么TCO需要操作码或它会做什么.据我所知,能够进行TCO的要求是递归调用的结果不与当前函数范围中的任何变量组合.如果你没有那个,那么我看不到操作码如何阻止你必须保持堆栈框架打开.如果你有,那么编译器是否总能轻易地将其编译为迭代的东西?
那么操作码有什么意义呢?显然有一些我不知道的东西.在完全可以使用TCO的情况下,不能总是在编译器级别处理,而不是在操作码级别处理?什么是不能的例子?
按照你已经提供的链接,这是我觉得的部分,非常接近你的问题.
CLR和尾调用
当您处理由CLR管理的语言时,有两种编译器在起作用.编译器从您的语言源代码到IL(C#开发人员将其称为csc.exe),然后是从IL到本机代码的编译器(在运行时调用的JIT 32/64位编译器)或NGEN时间).source-> IL和IL-> native编译器都理解尾调用优化.但是IL->本机编译器 - 我将其简称为JIT - 对最终是否将使用尾调用优化有最终决定权.source-> IL编译器可以帮助生成有助于进行尾调用的IL,包括使用"tail".IL前缀(稍后会详细介绍).通过这种方式,source-> IL编译器可以构造它生成的IL,以说服JIT进行尾调用.但是JIT总是可以选择做任何想做的事情.
JIT何时进行尾调用?
我问起了大楼里的邻居Fei Chen和Grant Richins,他们碰巧在JIT工作,在什么条件下各种JIT都会采用尾调优化.完整的答案相当详细.快速总结是JIT尝试尽可能地使用尾调用优化,但是有很多原因导致无法使用尾调用优化.尾调用的一些原因是非选项:
- 呼叫后呼叫者不会立即返回(duh :-))
- 调用者和被调用者之间的堆栈参数是不兼容的,这种方式需要在调用者执行之前在调用者的帧中移动东西
- 调用者和被调用者返回不同的类型
- 我们内联调用(内联比尾调用更好,并为更多优化打开了大门)
- 安全受到阻碍
- 调试器/分析器关闭了JIT优化
在你的问题的上下文中最有趣的部分,在我看来,在许多场景中,它是非常明确的,是上面提到的安全性的例子 ......
在许多情况下,.NET中的安全性取决于堆栈是否准确... 在运行时 ..这就是为什么,如上所述,CIL编译器的源和(运行时)CIL到本机JIT 共享负担.编译器,最后的说法是后者.
归档时间: |
|
查看次数: |
436 次 |
最近记录: |