Как определить, использует ли программа динамическую диспетчеризацию, посмотрев на сборку - PullRequest
4 голосов
/ 03 апреля 2012

Я прочитал пост на Reddit на Херб Заикание: JIT никогда не будет таким же быстрым, как нативный , и кто-то сказал, что это невероятно, что кто-то по имени Херб "дезинформирован", что C # использует виртуальные методы вместо-virtual (вы можете прочитать статью здесь ).Это заставило меня задуматься, и я сделал небольшую небольшую программу и заметил, что 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]

Правильно ли я считаю, что это динамическая диспетчеризация?Если так, есть ли другие контрольные знаки?Если я ошибаюсь, как я могу определить, является ли это динамическая отправка или нет?

Ответы [ 2 ]

3 голосов
/ 03 апреля 2012

косвенный вызов, например, call dword ptr [eax+000000D8h] является признаком использования виртуальной таблицы

2 голосов
/ 03 апреля 2012

Да, этот шаблон, который ищет похожую на vtable вещь и затем использует извлеченный адрес для выполнения вызова функции

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

является признаком динамической диспетчеризации (также называемой динамической привязкой).Шаблон в основном делает следующее: используя адрес объекта, он выводит тип объекта (на самом деле он просто находит указатель виртуальной таблицы, хранящийся внутри объекта) и находит, какую функцию вызывать (зная ее индекс в виртуальной таблице).Альтернатива в случае, если вы уже знаете фактический тип объекта, - просто вызвать нужную функцию напрямую.

Например, в C ++:

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

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

Здесь у компилятора достаточно данных, чтобы знатьobject хранит адрес объекта типа class Class, поэтому он может просто генерировать прямой (без просмотра vtable) вызов Class::Method(), что, конечно, быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...