为什么JVM具有最大内联深度?

Rya*_*ard 17 java jit jvm

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

(这是由JitWatch提示我显示深度嵌套的Guava checkArgument调用由于深度没有内联)

Old*_*eon 12

一些重要的搜索揭示了这个有趣的小片段(我实际上已经到了谷歌搜索的第4页):

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

这表明,MaxInlineLevel在您停止内联之前,对您的深度的预期是一个很大的限制.它还建议MaxRecursiveInlineLevel只引用直接递归调用,而不是调用递归调用,如foo()调用bar()调用foo().

所以我认为我的猜测是正确的 - MaxInlineLevel是为了防止相互递归,因为检测到你需要保持对内联调用堆栈的完整深度的引用.

MaxInlineResursionLevel控制内联foo()调用foo().

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

@apangin的评论从Open JDK 8中找到一个更现代的热点版本,这表明它现在不再像那样简单了.看起来整个堆栈都在搜索递归调用,因此现在也可以阻止相互递归过去MaxRecursiveInlineLevel.

  • @TagirValeev不完全是,但我想基本原因是保持简单.无限的内联深度会增加复杂性,编译时间和内存使用可能不太可预测(对于AOT编译器来说是可以的,但对于JIT则没有).还要记住,编译后的代码应该在运行时跟踪整个内联树(以便能够展开和去优化).虽然我认为9的默认值已经过时了.它已经很久没有改变,但是现在,随着更多的资源可用,考虑到溪流和lamdas,肯定有一个改进的地方. (6认同)
  • 你看看很老的消息来源.正确的地方是[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)递归调用. (3认同)
  • 深入挖掘.[循环](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构造函数中设置. (3认同)