Adres etykiet (MSVC)

Piszemy kod bajtowy dla skompilowanego języka wysokiego poziomu, a po odrobinie profilowania i optymalizacji, stało się jasne, że obecny największy narzut wydajności jest instrukcją switch, której używamy, aby przejść do przypadków kodu bajtowego.

Zbadaliśmy wyciągnięcie adresu każdej etykiety przypadku i przechowywanie go w strumieniu samego kodu bajtowego, a nie ID instrukcji, które zwykle włączamy. Jeśli to zrobimy, możemy pominąć tabelę skoków i bezpośrednio przejść do położenie kodu aktualnie wykonywanej instrukcji. Działa to fantastycznie w GCC, jednak MSVC nie wydaje się obsługiwać takiej funkcji.

Próbowaliśmy użyć inline assembly, aby pobrać adres etykiet (i przejść do nich), i to działa, jednak użycie inline assembly powoduje, że cała funkcja jest unikana przez optymalizator MSVC.

Czy istnieje sposób, aby optymalizator nadal działał nad kodem? Niestety, nie możemy wyodrębnić montażu inline do inna funkcja niż ta, w której etykiety zostały wykonane, ponieważ nie ma sposobu, aby odwołać się do etykiety dla innej funkcji, nawet w montażu inline. Jakieś pomysły lub pomysły? Twój wkład jest bardzo mile widziany, dzięki!

Author: Deduplicator, 2011-06-21

3 answers

Jedynym sposobem na zrobienie tego w MSVC jest użycie inline assembly (co w zasadzie przeszkadza ci w x64):

int _tmain(int argc, _TCHAR* argv[])
{
case_1:
    void* p;
    __asm{ mov [p],offset case_1 }
    printf("0x%p\n",p);
    return 0;
}

Jeśli planujesz zrobić coś takiego, to najlepszym sposobem byłoby napisanie całego interpretera w assembly, a następnie połączenie go z głównym kodem binarnym za pomocą linkera(To właśnie zrobił LuaJIT i jest to główny powód, dla którego maszyna wirtualna jest tak ślepo szybka, gdy nie działa JIT ' owy kod).

LuaJIT jest open-source , więc możesz wyciągnąć z niego kilka wskazówek jeśli pójdziesz tą drogą. Alternatywnie możesz zajrzeć do źródła forth (którego twórca rozwinął zasadę , której próbujesz użyć), jeśli istnieje MSVC, możesz zobaczyć, jak to zrobili, w przeciwnym razie utknąłeś z GCC (który nie jest złą rzeczą, działa na wszystkich głównych platformach).

 15
Author: Necrolis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-15 10:44:20

Zobacz, co Erlang robi w budowaniu na oknach. Używają MSVC dla większości kompilacji, a następnie GCC dla jednego pliku, aby użyć rozszerzenia labels-as-values. Wynikowy kod obiektowy jest następnie hakowany, aby był kompatybilny z LINKEREM MSVC.

Http://www.erlang.org/doc/installation_guide/INSTALL-WIN32.html

 10
Author: goertzenator,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-03 15:17:57

Wydaje się, że można po prostu przenieść rzeczywisty kod do funkcji, zamiast etykiet liter. Kod bajtowy może być następnie trywialnie przekształcony w wywołania bezpośrednie. Kod bajtowy 1 tłumaczyłby się na CALL BC1. Ponieważ generujesz połączenia bezpośrednie, nie masz narzutu wskaźników funkcji. Potoki większości procesorów mogą podążać za takimi bezwarunkowymi odgałęzieniami bezpośrednimi.

W rezultacie, rzeczywiste implementacje każdego kodu bajtowego są zoptymalizowane, a konwersja z kodu bajtowego do kodu machince jest trywialną konwersją 1:1. Dostajesz trochę rozszerzenia kodu, ponieważ każdy CALL mA 5 bajtów (zakładając x86-32), ale jest to mało prawdopodobne, aby był to poważny problem.

 3
Author: MSalters,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-15 07:47:53