4

ハーブスタッターのRedditに関する投稿を読みました:JITはネイティブほど速くなることはなく、誰かがハーブと呼ばれる誰かが非仮想ではなく仮想メソッドを使用していることを「誤解」しているとコメントしました(記事はこちらで読むことができます) )。それは私に考えさせられました、そして私は簡単な小さなプログラムを作りました、そしてC#が実際にCILのための仮想メソッド(callvirt対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]

これが動的ディスパッチであると仮定して正しいですか?もしそうなら、他に物語の兆候はありますか?私が間違っている場合、それが動的ディスパッチであるかどうかをどのように判断できますか?

4

2 に答える 2

3

間接呼び出しなどcall dword ptr [eax+000000D8h] は、仮想テーブルを使用する兆候です

于 2012-04-03T15:04:16.490 に答える
2

はい、vtable のようなものを検索し、取得したアドレスを使用して関数呼び出しを実行するこのパターン

 00000032  mov         eax,dword ptr [ecx] 
 00000034  call        dword ptr [eax+000000D8h]

動的ディスパッチ (動的バインディングとも呼ばれます) の兆候です。このパターンは基本的に次のことを行います: オブジェクトのアドレスを使用してオブジェクト タイプを推定し (実際には、オブジェクト内に格納されている vtable ポインターを見つけるだけです)、呼び出す関数を見つけます (vtable 内のインデックスを認識します)。オブジェクトの実際のタイプがすでにわかっている場合の代替手段は、適切な関数を直接呼び出すことです。

たとえば、C++ では次のようになります。

class Class {
public:
    virtual void Method() {}
};

Class* object = new Object();
object->Method();
delete object;

ここで、コンパイラはobjectが type の object のアドレスを格納していることを知るのに十分なデータを持っているため、もちろんより高速class Classな直接 (vtable ルックアップなし) 呼び出しを発行できます。Class::Method()

于 2012-04-03T14:59:10.543 に答える