2015-09-10 103 views
13

java有一个参数-XX:MaxInlineLevel(默认值为9),它控制嵌套调用的最大数量。为什么会有这样的限制?为什么不是基于频率和代码大小的通常启发式算法足以让JVM自己决定内联的深度?为什么JVM具有最大内联深度?

(这是由JitWatch促使我展示一个深度嵌套番石榴checkArgument呼吁没有被内联,由于深度)

+0

完全不确定,但可能是为了避免相互递归陷阱,这可能难以/昂贵地以其他方式进行辩护。 – OldCurmudgeon

+1

@OldCurmudgeon,但你有MaxRecursiveInlineLevel – MrSimpleMind

+0

@MrSimpleMind - 有趣 - 我显然是错的。必须是其他原因。 – OldCurmudgeon

回答

10

一些显著搜索揭示了这个有趣的小fragment(事实上,我尽可能页谷歌搜索的):

if (inline_depth() > MaxInlineLevel) { 
     return "inlining too deep"; 
    } 
    if (method() == callee_method 
      && inline_depth() > MaxRecursiveInlineLevel) { 
     return "recursively inlining too deep"; 
    } 

这表明MaxInlineLevel为预期的硬性限制,以停止内联之前,你有多深。它还暗示MaxRecursiveInlineLevel仅指直接递归调用,而不是诸如foo()调用bar()的调用递归调用,其调用foo()

因此,我认为我是对我的猜测评论 - MaxInlineLevel是防止相互递归因为检测到您需要保持引用的内联调用堆栈的最大深度。

MaxInlineResursionLevel控件foo()调用foo()内联。

请注意,引用的代码可能不是真正的JVM。

@apangin的评论从Open JDK 8找到了更现代化的热点版本,这表明它现在不再那么简单了。它看起来像整个堆栈搜索递归调用,所以现在可以阻止相互递归通过MaxRecursiveInlineLevel

+3

你看看很老的来源。正确的地方在[hg.openjdk.java.net](http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/)。 'MaxRecursiveInlineLevel'计入[直接和间接](递归调用)(http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/c1374141598c/src/share/vm/opto/bytecodeInfo.cpp#l389)递归调用。 – apangin

+0

@apangin - 这似乎没有做什么评论说。它也只是与'MaxRecursiveInlineLevel'进行比较。虽然好发现。 – OldCurmudgeon

+3

深入挖掘。 [The loop](http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/c1374141598c/src/share/vm/opto/bytecodeInfo.cpp#l401)遍历所有框架,查看被调用方法出现在堆栈的任何地方。 [MaxInlineLevel](http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/c1374141598c/src/share/vm/opto/bytecodeInfo.cpp#l380)现在在InlineTree构造函数中设置。 – apangin

相关问题