2014-04-06 14 views
26

Myślę, że obserwuję kompilator .NET JIT, nie podpowiadając ani nie optymalizując wywołań wywołania pustych metod statycznych, które nie mają skutków ubocznych, co jest nieco zaskakujące, biorąc pod uwagę pewne zasoby internetowe.Dlaczego kompilator .NET JIT miałby decydować o nieinwazyjnym lub optymalizującym wywoływaniu połączeń wychodzących do pustych metod statycznych, które nie mają skutków ubocznych?

Moje środowisko to Visual Studio 2013 na x64, Windows 8.1, .NET Framework 4.5.

Biorąc pod uwagę to prosty program testowy (https://ideone.com/2BRCpC)

class Program 
{ 
    static void EmptyBody() 
    { 
    } 

    static void Main() 
    { 
     EmptyBody(); 
    } 
} 

kompilacji uwolnienia z optymalizacje powyższego programu produkuje następujące MSIL dla Main i EmptyBody:

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  6 (0x6) 
    .maxstack 8 
    IL_0000: call  void Program::EmptyBody() 
    IL_0005: ret 
} // end of method Program::Main 

.method private hidebysig static void EmptyBody() cil managed 
{ 
    // Code size  1 (0x1) 
    .maxstack 8 
    IL_0000: ret 
} // end of method Program::EmptyBody 

To nie jest zaskakujące, że MSIL zawiera wywołanie z Main do EmptyBody, ponieważ kompilator C# nie powinien inline ani optymalizować takich połączeń. Jednak myślałem, że kompilator JIT będzie następnie inline lub optymalizacji od tej rozmowy. Ale tak się nie wydaje.

Jeśli uruchomić powyższy program i debuger w Main wygenerowany montaż jest taka:

00572621 mov   ebp,esp 
00572623 cmp   dword ptr ds:[4320B84h],0 
0057262A je   00572631 
0057262C call  73E6AF20 
00572631 call  dword ptr ds:[4321578h] 

wskaźnik instrukcji jest natychmiast ustawiany na ostatnią linię na 00572631, który jest wywołanie EmptyBody . Wkraczającego EmptyBody wygenerowany montaż okaże się

00BD2651 mov   ebp,esp 
00BD2653 cmp   dword ptr ds:[4B00B84h],0 
00BD265A je   00BD2661 
00BD265C call  73E6AF20 
00BD2661 nop 
00BD2662 pop   ebp 
00BD2663 ret 

wskaźnik instrukcji jest natychmiast ustawiona na linii nop w 00BD2661, który nic nie robi, a ja nie mogę odgadnąć, dlaczego jest ona generowana w pierwszej kolejności.

Biorąc pod uwagę, że dwa powyższe fragmenty zestawu mają ten sam nagłówek instrukcji 4, zakładam, że jest to zwykła tablica kotłów z wejściami do metody, w której ustawiono stos i tym podobne. Jestem zapalonym nauczyć się wiedzieć, co te powtarzające instrukcje zrobi, choć:

00BD2653 cmp   dword ptr ds:[4B00B84h],0 
00BD265A je   00BD2661 
00BD265C call  73E6AF20 

Tak czy inaczej, główne pytanie brzmi: Dlaczego kompilator JIT montaż produktów, które wywołuje pusty mocny metody statycznej EmptyBody?

+9

Nie jestem ekspertem od C#. ale obserwując system zmienia to;) Możesz zobaczyć kod emitowany w całości dla dobra twojego debuggera. –

+0

Prawda. Jestem ciekawy, jak można się zorientować, czy połączenie zostało zoptymalizowane, czy nie, co rzekomo zauważyły ​​niektóre z "potwierdzonych zasobów internetowych" :-) –

+0

@JohannGerell wyłączyć flagę debugowania i skompilować do wydania i załącz debuggera w czasie wykonywania, dzięki temu będziesz debugować rzeczywisty kod. Nie wierzę, że JIT będzie monitorować debuggera, aby sprawdzić, czy jest on później dołączony i na tej podstawie dokonać zmian w asmie. – rolls

Odpowiedz

31

Po głębszym wykopaniu okazuje się, że sam mogę odpowiedzieć na to pytanie. Jak wyjaśniono w http://blogs.msdn.com/b/vancem/archive/2006/02/20/535807.aspx, obserwowanie demontażu zoptymalizowanej wersji wydania pod debuggerem domyślnie wpłynie na kompilator JIT.

Odznaczenie te

  • 'Wyłącza optymalizację JIT na obciążenia modułu'
  • 'Włącz Just My Code'

pod VS> Narzędzia> Debugowanie> Ogólne pokaże "prawdziwe" Wynik kompilacji JIT, który dla połączenia z EmptyBody w powyższym Main jest następujący:

004C2620 ret 

Oznacza to, że połączenie z EmptyBody zostało całkowicie usunięte, co było oczekiwane, a świat wciąż jest szczęśliwym i dość przewidywalnym miejscem do życia :)

+2

"Nop" to martwy gratisów, że tak się dzieje. Jeśli je widzisz, wiesz co robić :) –

+0

W powiązanym artykule na blogu jest napisane to samo: nie powinno być "nop", jeśli zastosowałeś się do zaleceń poprawnie. –

Powiązane problemy