我正在尝试制作一个简短的 C# 片段来说明 Assembly.GetCallingAssembly()
行为因 JIT 内联而发生的变化 outlined in MSDN .到目前为止,这是我的代码:
class Program
{
static void Main(string[] args)
{
Console.WriteLine( GetAssembly().FullName );
Console.ReadLine();
}
static Assembly GetAssembly()
{
return System.Reflection.Assembly.GetCallingAssembly();
}
}
我在“Release”中构建并开始使用“Start Without Debugging”- 此设置从 this answer 生成代码招致内联。我看到的结果是
ConsoleApplication2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
很明显 GetAssembly()
没有内联到 Main()
中,否则我会将 mscorlib
视为调用程序集。
我已经检查了所有内联标准,但我不明白为什么 GetAssembly()
不会被内联。
是否有可能知道 JIT 编译器决定不内联调用的确切原因?
最佳答案
这是 .NET 3.5 中 Assembly.GetCallingAssembly() 的声明:
[MethodImpl(MethodImplOptions.NoInlining)]
public static Assembly GetCallingAssembly()
{
StackCrawlMark lookForMyCallersCaller = StackCrawlMark.LookForMyCallersCaller;
return nGetExecutingAssembly(ref lookForMyCallersCaller);
}
StackCrawlMark 枚举很有趣,当调用者将被内联时,“查找我的调用者调用者”不能很好地工作。在声明枚举的 thread.cs 的 SSCLI20 源代码中有一条注释:
declaring a local var of this enum type and passing it by ref into a function that needs to do a stack crawl will both prevent inlining of the calle [sic] and pass an ESP point to stack crawl to
这与 GetCallingAssembly() 中发生的事情非常匹配,它是一个局部变量并且确实被 ref 传递。不确定机制是什么,但是抖动可以产生一个名为 CORINFO_FLG_BAD_INLINEE 的方法属性。这反过来强制调用 MethodDesc::SetNotInline()。这是一个猜测,这是非常模糊的。
关于c# - 为什么我的方法调用 Assembly.GetCallingAssembly() 不是 JIT 内联的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12910167/