为了实现尾调用优化,JVM需要牺牲什么?

3
3个回答

6

虽然不同(因为il指令已经存在),但值得注意的是.Net 64位JIT团队必须付出额外的努力来尊重所有尾调用。

我特别提到以下评论:

当然,缺点是如果您需要调试或分析优化代码,请准备处理看起来少了几个框架的调用堆栈。

我认为JVM也很难避免这种情况。

考虑到在要求尾调用优化的情况下,JIT应该假定它是必需的以避免堆栈溢出,因此这不是可以在调试版本中关闭的东西。如果在有趣的部分之前崩溃,那么它们对于调试毫无用处。实际上,“优化”是一个永久性功能,并且会影响受其影响的堆栈跟踪。

值得指出的是,任何避免在执行程序员在概念上描述/理解为堆栈操作(例如调用函数)的操作时创建真正的堆栈帧的优化都会导致在调试/提供堆栈跟踪时呈现给用户的内容与实际情况不符。这是不可避免的,因为描述操作的代码与执行操作的状态机的机制越来越分离。

2
目前正在进行为 JVM 添加尾调用的工作。这里有一个维基页面讨论了一些细节。

0

通常情况下,实现尾调用优化(TCO)会防止您获得完整的堆栈跟踪。这是不可避免的,因为TCO的整个目的是避免创建额外的堆栈帧。

值得注意的是,Clojure还具有一种非堆栈消耗的“recur”功能,以解决当前JVM版本上的这个限制。

例如:

(defn triangle [n accumulator] 
  (if 
    (<= n 0)  
      accumulator
      (recur (dec n) (+ n accumulator))))

(triangle 1000000 0)

=> 500000500000     (note stack does not explode here!)

如果编译器不能自动检测到尾递归,你会称之为“特性”吗?我会称之为“变通方法”。 - Ingo
@Ingo - 实际上,这是Rich Hickey的设计决策。他想要使TCO显式化 - 如果您想要它,必须请求它。请参见例如https://groups.google.com/forum/#!topic/clojure/4bSdsbperNE - mikera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接