我在应用程序中观察到许多“堆栈内省(introspection)”代码,这些代码通常隐式地依赖于其包含方法未被内联以确保其正确性。此类方法通常涉及调用:
MethodBase.GetCurrentMethod
Assembly.GetCallingAssembly
Assembly.GetExecutingAssembly
现在,我发现有关这些方法的信息非常困惑。我听说运行时不会内联调用 GetCurrentMethod 的方法,但我找不到任何相关文档。我曾多次在 StackOverflow 上看到过帖子,例如 this one ,表明 CLR 不会内联跨程序集调用,但 GetCallingAssembly
documentation强烈表明否则。
还有备受诟病的 [MethodImpl(MethodImplOptions.NoInlined)]
,但我不确定 CLR 是否认为这是“请求”或“命令”。
请注意,我是从契约(Contract)的角度询问内联资格,不是关于 JITter 的当前实现何时由于实现困难而拒绝考虑方法,或者关于当 JITter 在评估权衡后最终选择内联一个合格的方法时。我已阅读this和 this ,但他们似乎更关注最后两点(偶尔提到了 MethodImpOptions.NoInlined 和“异国情调的 IL 指令”,但这些似乎是作为启发法而不是义务来呈现的)。
什么时候CLR允许内联?
最佳答案
这是一个抖动实现细节,x86 和 x64 抖动的规则略有不同。这在致力于抖动的团队成员的博客文章中被随意记录,但团队当然保留更改规则的权利。看起来您已经找到它们了。
肯定支持来自其他程序集的内联方法,如果不是这样的话,许多 .NET 类将工作得非常糟糕。当您查看为 Console.WriteLine() 生成的机器代码时,您可以看到它的工作原理,当您传递一个简单的字符串时,它通常会被内联。要亲眼看到这一点,您需要切换到发布版本并更改调试器选项。工具+选项、调试、常规,取消选中“抑制模块加载时的 JIT 优化”。
否则没有充分的理由认为 MethodImpOptions.NoInlined 受到诽谤,这几乎就是它存在的首要原因。事实上,它在 .NET 框架中有意用于许多调用内部辅助方法的小型公共(public)方法。它使异常堆栈跟踪更容易诊断。
关于.net - 方法什么时候可以被 CLR 内联?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4660004/