Где хранить константы кода при написании JIT-компилятора?

Я пишу JIT-компилятор для x86-64, и у меня есть вопрос относительно наилучшей практики для включения констант в машинный код, который я генерирую.

Мой подход пока прост:

  • Выделите кусок памяти RW с помощью VirtualAlloc или же mmap
  • Загрузите машинный код в указанную область памяти.
  • Пометить страницу как исполняемую VirtualProtect или же mprotect (и удалите привилегию записи для безопасности).
  • Выполнить.

Когда я генерирую код, я должен включать константы (числовые, строковые), и я не уверен, как лучше всего это сделать. Я имею в виду несколько подходов:

  • Сохраните все константы как непосредственные значения в кодах операций инструкций. Это кажется плохой идеей для всего, кроме, может быть, небольших скалярных значений.
  • Выделите отдельную область памяти для констант. Это кажется мне лучшей идеей, но это немного усложняет управление памятью и рабочий процесс компиляции - мне нужно знать место в памяти, прежде чем я смогу начать писать исполняемый код. Также я не уверен, что это как-то влияет на производительность из-за худшего локального пространства памяти
  • Сохраните константы в той же области, что и код, и получайте к ним доступ с помощью RIP-относительной адресации. Мне нравится этот подход, так как он объединяет соответствующие части программы, но мне немного неловко смешивать инструкции и данные.
  • Что-то совершенно другое?

Каков предпочтительный способ пойти по этому поводу?

1 ответ

Решение

Многое зависит от того, как вы генерируете свой двоичный код. Если вы используете JIT-ассемблер, который обрабатывает метки и вычисляет смещения, все довольно просто. Вы можете прикрепить константы в блоке после конца кода, используя относительные к ПК ссылки на эти метки, и в итоге получите один блок байтов с кодом и константами (простое управление). Если вы пытаетесь сгенерировать двоичный код на лету, у вас уже есть проблема выяснения того, как обрабатывать прямые относительные ссылки на ПК (например, для прямых ветвей). Если вы используете back-patch, вам нужно расширить его для поддержки ссылок на ваш блок констант.

Вы можете избежать вычислений относительного смещения для ПК, поместив константы в отдельный блок и передав адрес этого блока в качестве параметра в свой код. Это в значительной степени "Выделите отдельный регион для констант", который вы предлагаете. Вам не нужно знать адрес блока, если вы передаете его в качестве аргумента.

Другие вопросы по тегам