我在 Herb Stutter: JIT will never be as fast as native 上阅读了 Reddit 上的帖子有人发表评论说,令人难以置信的是有人称 Herb “误导”了 C# 使用虚拟方法而不是非虚拟方法(您可以阅读文章 here)。这让我开始思考,我制作了一个快速的小程序,并注意到 C# 确实为 CIL 生成了虚拟方法(callvirt vs call)。但后来有人告诉我这并不容易,而且 JIT 可能会内联代码,而不是使用 vtables 和动态调度。我启动了调试器并试图查看。这是我的简单程序:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Test t = new Test();
t.TestIt();
t.TestOut();
}
}
class Test
{
public Test() { }
public void TestIt()
{
Console.WriteLine("TESTIT");
}
public void TestOut()
{
Console.WriteLine("TESTOUT");
}
}
}
然后这里是程序集:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Test t = new Test();
00000000 push ebp
00000001 mov ebp,esp
00000003 push esi
00000004 mov ecx,439E68h
00000009 call FFCE0AD4
0000000e mov esi,eax
t.TestIt();
00000010 call 704BBEB8 // Call to Console.WriteLine()
00000015 mov ecx,eax
00000017 mov edx,dword ptr ds:[02A02088h]
0000001d mov eax,dword ptr [ecx]
0000001f call dword ptr [eax+000000D8h]
t.TestOut();
00000025 call 704BBEB8 // Call to Console.WriteLine()
0000002a mov ecx,eax
0000002c mov edx,dword ptr ds:[02A0208Ch]
00000032 mov eax,dword ptr [ecx]
00000034 call dword ptr [eax+000000D8h]
0000003a pop esi
}
0000003b pop ebp
0000003c ret
我的问题是:通过查看程序集如何判断它是否使用动态调度?我的预感是因为这 4 条指令与我内存中的编程语言课很相似:
0000002a mov ecx,eax
0000002c mov edx,dword ptr ds:[02A0208Ch]
00000032 mov eax,dword ptr [ecx]
00000034 call dword ptr [eax+000000D8h]
我假设这是动态调度是否正确?如果是这样,是否还有其他明显的迹象?如果我错了,我怎么能判断它是否是动态调度?
最佳答案
间接调用,例如call dword ptr [eax+000000D8h]
是使用虚拟表的标志
关于oop - 如何通过查看程序集来判断程序是否使用动态调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9995922/