Бранд Букер (Brandt Bucher) от Microsoft, част от основните разработчици на CPython и работещ в екип, занимаващ се с увеличаване на производителността на интерпретатора CPython, публикува реализация на JIT компилатор за Python, използваща техниката Copy-and-Patch. Публикацията на JIT е свързана с Коледа и анонсът е написан в стихове.
Предложеният JIT се отличава с много висока скорост на генериране на код, простота на поддръжка и пълна интеграция с интерпретатора. Предложеният метод позволява автоматично преобразуване на интерпретатора, написан на C, в JIT компилатор, без отделно изграждане на логиката за генериране на код и без ръчно създаване на асемблерни представяния. С този подход, поправка на грешка в интерпретатора автоматично ще доведе до решаване на същата проблема и в JIT, тъй като се използва общ генератор на код.
Методът Copy-and-Patch се основава на факта, че релокацията на код в паметта при зареждане от линкера на обектни файлове и заместването на машинни инструкции вместо байт код в JIT са сходни задачи. При работа на JIT по време на изпълнението на програмата се извършва обход на създадените от интерпретатора инструкции на байт код и копиране на предварително скомпилирания машинен код за всяка инструкция в областта на паметта с изпълняем код, както и динамична промяна на инструкциите за подмяна на обработваните данни (JIT копира готови шаблони на вече скомпилирани функции и вмъква в тях необходимите стойности, като аргументи и константи). При зареждане на обектни файлове също се извършва копиране на машинния код в паметта и подмяна на външни символи.
В Copy-and-Patch JIT, използвайки LLVM, се събира обектен файл в ELF формат, съдържащ данни за инструкциите на байткода и информация за необходимите замени на данни. JIT заменя генерираните по време на интерпретацията на програмата инструкции на байткода с представяния в машинен код, като намества необходимите за изчисления данни. Реализацията на JIT изисква LLVM като зависимост по време на компилацията, но компонентите за изпълнение не са свързани с външни зависимости и се свеждат до приблизително 300 ръчно написани реда на C и 3000 генерирани реда код на C.
В сравнение с традиционния JIT инструментариум (LLVM -O0), предложеното JIT осигурява 100 пъти по-бърза генерация на код и 15% по-бърз резултатен код. В сравнение с компилацията в WebAssembly (Liftoff), новото JIT генерира код 5 пъти по-бързо, а полученото код работи 50% по-бързо. Ако сравним новото JIT с оптимизиращото JIT (LuaJIT), което използва ръчно написан код на асемблер, предложената версия е по-бърза в 13 от 44 теста, а в средно е изостанала по производителност с 35%, при значително опростяване на поддръжката и намаляване на сложността на реализацията.

Източник: opennet.ru
