Перекомпіляція

програмне забезпечення

В інформатиці динамічна перекомпіляція (іноді скорочена до dynarec або псевдо-акронім DRC) є особливістю деяких емуляторів та віртуальних машин, де система може перекомпілювати якусь частину програми під час виконання. Компілюючи під час виконання, система може адаптувати згенерований код, щоб відображати середовище виконання програми, і потенційно може виробляти більш ефективний код, використовуючи інформацію, недоступну для традиційного статичного компілятора.

Використання

ред.

Більшість динамічних рекомпіляторів використовуються для перетворення машинного коду між архітектурами під час виконання. Це завдання часто потрібне при емуляції застарілих ігрових платформ. В інших випадках система може застосовувати динамічну рекомпіляцію як частину адаптивної стратегії оптимізації для виконання переносного представлення програми, такого як байт-коди Java або .NET Common Language Runtime. Повношвидкісні налагоджувачі також використовують динамічну рекомпіляцію, щоб зменшити накладні витрати на простір, що виникають у більшості методів деоптимізації, та інші функції, такі як динамічна міграція потоків.

Завдання

ред.

Основними завданнями, які повинен виконувати динамічний рекомпілятор, є:

  • Читання машинного коду з вихідної платформи
  • Видає машинний код для цільової платформи

Динамічний рекомпілятор може також виконувати деякі допоміжні завдання:

  • Керування кешем перекомпільованого коду
  • Оновлення підрахунку минулого циклу на платформах за допомогою регістрів підрахунку циклів
  • Управління перевіркою переривань
  • Надання інтерфейсу для віртуалізованого обладнання підтримки, наприклад, графічного процесора
  • Оптимізація структур коду вищого рівня для ефективної роботи на цільовому обладнанні (див. нижче)

Приклади

ред.

Припустимо, програма запускається в емуляторі і їй потрібно скопіювати рядок із нульовим закінченням. Програма складена спочатку для дуже простого процесора. Цей процесор може одночасно копіювати лише байт, і це потрібно робити, спочатку зчитуючи його з вихідного рядка в регістр, а потім записуючи з цього реєстру в рядок призначення. Оригінальна програма може виглядати приблизно так:

beginnig:

   mov A,[first string pointer]    
   mov B,[second string pointer]   
   
loop:

   mov C,[A]            
   mov [B],C        
   inc A                
   inc B                
   cmp C,#0             
    jnz loop           

end:

Можливо, емулятор працює на схожому процесорі, але надзвичайно добре копіює рядки, і емулятор знає, що може цим скористатися. Він може розпізнати послідовність інструкцій щодо копіювання рядків та вирішити переписати їх ефективніше користування перед виконанням, щоб скористатися емуляцією.

Скажімо, є інструкція щодо нашого нового процесора під назвою movs, спеціально розроблена для ефективного копіювання рядків. Наша теоретична інструкція movs копіює 16 байтів за раз, без необхідності завантаження їх у регістр C між ними, але в центрі, якщо копіює 0 байт (що визначає кінець рядка) і встановлює нульовий прапор. Він також знає, що адреси рядків будуть у реєстрації A та B, а потім він збільшує A та B на 16 кожного разу, коли він виконується, готовий до наступної копії.

Наш новий перекомпонований код може виглядати приблизно так:

beginnig:

   mov A,[first string pointer]    
   mov B,[second string pointer]   

loop:

   movs [B],[A]            
    jnz loop              

end:

Існує негайна перевага в швидкості просто тому, що процесору не потрібно завантажувати стільки інструкцій, щоб виконати одне і те ж завдання, а й тому, що інструкція movs, ймовірно, буде оптимізована дизайнером процесора, щоб бути ефективнішою, ніж послідовність, яка використовується в перший приклад. Наприклад, він може краще використовувати паралельне виконання в процесорі для збільшення A і B, поки він ще копіює байти.

Приклади використання

ред.

Приклади в програмах

ред.

Багато віртуальних машин Java мають динамічну рекомпіляцію.

Apple's Rosetta для Mac OS X на x86, дозволяє запускати код PowerPC на архітектурі x86.

Пізніші версії емулятора Mac 68K, що використовуються в класичній Mac OS, для запуску коду 680x0 на апаратному забезпеченні PowerPC.

Psyco, спеціалізований компілятор для Python.

Проект HP Dynamo, приклад прозорого двійкового динамічного оптимізатора.

DynamoRIO, наступник Dynamo з відкритим кодом, який працює з наборами інструкцій ARM, x86-64 та IA-64 (Itanium).

Віртуальна машина Vx32 використовує динамічну перекомпіляцію для створення незалежних від ОС пісочниць архітектури x86 для безпечних додатків.

Віртуальний ПК Microsoft для Mac, який використовується для запуску коду x86 на PowerPC.

QEMU, емулятор повноцінної системи з відкритим кодом.

FreeKEYB, міжнародний DOS-драйвер клавіатури та консолі з багатьма покращеннями юзабіліті, використовував самомодифікуючий код та динамічне видалення мертвого коду, щоб мінімізувати його зображення в пам'яті на основі його конфігурації користувача (вибрані функції, мови, макети) та фактичного середовища виконання (варіант ОС та версія, завантажені драйвери, базове обладнання), автоматичне вирішення залежностей, динамічне переміщення та повторне поєднання розділів коду на рівні байтовості та оптимізація опстрингів на основі семантичної інформації, наданої у вихідному коді, інформації про переміщення, що генерується спеціальними інструментами під час складання та інформації профілю під час завантаження.

OVPsim, вільно доступний повний емулятор системи.

VirtualBox використовує динамічну рекомпіляцію.

Valgrind, інструмент програмування для налагодження пам'яті, виявлення витоків пам'яті та профілювання, використовує динамічну рекомпіляцію.

Приклади в іграх

ред.

MAME використовує динамічну рекомпіляцію в своїх емуляторах процесорів для MIPS, SuperH, PowerPC і навіть графічних процесорів Voodoo.

Wii64, емулятор Nintendo 64 для Wii.

WiiSX, емулятор Sony PlayStation для Nintendo Wii.

Mupen64Plus, багатоплатформовий емулятор Nintendo 64.

Yabause, багатоплатформовий емулятор Сатурна.

У функціоналах зворотної сумісності Xbox 360 (тобто запущених ігор, написаних для оригінального Xbox) широко застосовується динамічна рекомпіляція.

PPSSPP, портативний емулятор Sony PlayStation. Перекомпілятори для x86 та ARM.

PSEmu Pro, емулятор Sony PlayStation.

Ultrahle, перший емулятор Nintendo 64, який повністю запускає комерційні ігри.

PCSX2, [9] емулятор Sony PlayStation 2, має рекомпілятор під назвою «microVU», наступник «SuperVU».

Dolphin, емулятор Nintendo GameCube та Wii, має опцію Dynarec.

GCemu, [10] емулятор Nintendo GameCube.

NullDC, емулятор Sega Dreamcast для x86.

GEM, [11] емулятор Nintendo Game Boy для MSX використовує оптимізуючий динамічний рекомпілятор.

DeSmuME, [12] емулятор Nintendo DS, має опцію dynarec.

Soywiz's Psp, [13] портативний емулятор Sony PlayStation, має опцію dynarec.

RPCS3, емулятор Sony PlayStation 3. Перекомпілює як PPU, так і SPU на стільниковому процесорі для x86-64

Decaf-emu, емулятор Wii U, використовує динамічну перекомпіляцію (JIT) з PowerPC32 до обладнання коду x86_64 за допомогою бібліотеки libbinrec (сама бібліотека може працювати на будь-якій апаратній архітектурі).