Создание JIT-компилятора
Я написал реализацию Brainfuck (С++), которая работает следующим образом:
- Прочитать входной файл brainfuck
- Выполняют тривиальные оптимизации
- Преобразуйте мозговой код в машинный код для VM
- Выполнить этот машинный код в VM
Это довольно быстро, но узкое место теперь находится на виртуальной машине. Он написан на С++ и читает токен, выполняет действие (которого не так много, если вы знаете Brainfuck) и т.д.
То, что я хочу сделать, - это разграничить виртуальную машину и сгенерировать собственный машинный код на лету (так, в основном, JIT-компилятор). Это может быть легко ускорено в 20 раз.
Это означало бы, что шаг 3 заменяется компилятором JIT и шагом 4 с выполнением сгенерированного машинного кода.
Я не знаю, с чего начать, поэтому у меня есть несколько вопросов:
- Как это работает, как выполняется сгенерированный машинный код?
- Существуют ли библиотеки С++ для генерации собственного машинного кода?
Ответы
Ответ 1
-
Сгенерированный машинный код просто jmp
-ed или call
-ed как обычная функция. Иногда также требовалось отключить флаг отсутствия выполнения (бит NX) в памяти, содержащий сгенерированный код. В linux это делается с помощью mprotect(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC.)
В окнах NX называется DEP.
-
Есть некоторые... например. http://www.gnu.org/software/lightning/ - GNU Lightning (универсальный) и https://developer.mozilla.org/En/Nanojit - Nanojit, который используется в JavaScript JavaScript JIT. Более мощным и современным JIT является LLVM, вам просто нужно перевести BF-код в LLVM IR, а затем LLVM может делать оптимизацию и генерировать код для многих платформ или запускать LLVM IR на интерпретаторе (виртуальной машине) с возможностями JIT. Существует сообщение о BF и LLVM с полным компилятором LLVM JIT для BF http://www.remcobloemen.nl/2010/02/brainfuck-using-llvm/
Другой компилятор BF + LLVM находится здесь, в svn LLVM: https://llvm.org/svn/llvm-project/llvm/trunk/examples/BrainF/BrainF.cpp
Ответ 2
LLVM - полная библиотека С++ (или набор библиотек) для генерации собственного кода из промежуточной формы, в комплекте с документацией и примерами, и который использовался для создания JITters.
(Он также имеет компилятор C/С++, который использует фреймворк - однако сама фрейм может использоваться для других языков).
Ответ 3
Вот пример использования нового gcc-jit:
JIT-компиляция с использованием GCC 5
Он даже оптимизирует incs для констант.
Ответ 4
GNU Lightning - это набор макросов, которые могут генерировать собственный код для нескольких разных архитектур. Вам понадобится прочное понимание кода сборки, потому что ваш шаг 3 будет включать использование макросов Lightning для испускания машинного кода непосредственно в буфер, который вы позже выполните.