Как се работи с JIT

В някои вътрешни системи ние от Badoo използваме JIT за бързо търсене в голяма растерна карта. Това е много интересна и непозната тема. И за да поправя такава досадна ситуация, преведох полезна статия от Ели Бендерски за това какво е JIT и как да го използвам.
Преди това публикувах уводна статия за libjit за програмисти, които вече са запознати с JIT. Поне малко. В този пост аз описах накратко JIT и в него ще дам пълен преглед на JIT и ще го допълня с примери, кодът в който не изисква никакви допълнителни библиотеки.
Дефиниция на JIT
JIT е съкращение от „Just In Time“ или, ако се преведе на руски, „в движение“. Това не ни казва нищо и звучи така, сякаш няма нищо общо с програмирането. Струва ми се, че това описание на JIT е най-близко до истината:
Ако по време на изпълнението си програма създава и изпълнява някакъв нов изпълним код, който не е бил част от оригиналната програма на диск, това е JIT.
Самият термин JIT се появява за първи път в книгите за Java от Джеймс Гослинг. Айкок казва, че Гослинг е взел термина от промишленото производство и е започнал да го използва в началото на 90-те. Ако се интересувате от подробностите, прочетете статията на Icock. Сега нека видим как всичко описано по-горе работи на практика.
JIT: генерирайте машинен код и го стартирайте
Струва ми се, че JIT е по-лесно да се разбере, ако веднага го разделите на две фази:
- Фаза 1: генериране на машинен код, докато програмата работи
- Фаза 2: изпълнение на машинен код, докато програмата работи
Първата фаза е 99% от общата сложност на JIT. Но в същото време това е най-често срещаната част от процеса: точно това прави обикновеният компилатор. Добре известни компилатори като gcc и clang/llvm превеждат C/C ++ източниците в машинен код. Освен това машинният код обикновено се записва във файл, но няма смисъл да не се оставя в паметта (всъщност както gcc, така и clang/llvm имат готови функции за запазване на код в паметта за използване в JIT). Но в тази статия бих искал да се спра на втората фаза.
Изпълнение на генерирания код
Съвременните операционни системи са много избирателни относно това, което дадена програма може да прави, докато тя работи. Дните на дивия запад свършват с появата на защитен режим, който позволява на операционната система да присвоява различни права на различни парчета от паметта на процесите. Това означава, че в „нормален“ режим можете да разпределите памет в купчината, но не можете просто да изпълните кода, който е разпределен в купчината, без изрично да попитате първо операционната система.
Надявам се, че всички разбират, че машинният код е просто данни, колекция от байтове. Ето например, например: