Механизм, с помощью которого Common Lisp компилирует и загружает код в изображение

Недавно я читал о том, как современные ОС загружают исполняемые программы и выделяют для них память. К сожалению, у меня есть только книга по информатике на русском языке в качестве справочника, поэтому, пожалуйста, поправьте меня, если я ошибаюсь, но, похоже, современные ОС имеют разные разделы в исполняемой программе для данных и реальных команд процессора. Кроме того, нельзя отдать управление разделу данных, т.е. нельзя хранить там команду. Также невозможно изменить команду процессора в исполняемой (text) секции.

Отсюда вопрос: как это делает современный скомпилированный CL (SBCL, Clozure-CL)? Насколько я понимаю, он создает скомпилированные файлы FASL, а затем загружает их. Но видимые файлы FASL создаются при компиляции файла. Что происходит, когда вычисляется форма функции? Во-вторых, как CL загружает их (на уровне команд машины/ОС), чтобы для них была выделена правильная память? Кроме того, старый код должен быть каким-то образом разгружен.

PS. Конечно, это не проблема для интерпретируемых языков. А вот с JIT-компиляторами дело обстоит еще сложнее.


person mobiuseng    schedule 27.06.2018    source источник
comment
Я не могу дать полный ответ, но примерно так: исходный код > чтение > макрорасширение > компиляция > компоновка > загрузка > запуск. Типичный способ работы с формами верхнего уровня — скомпилировать их в некую анонимную функцию верхнего уровня, которая вызывается для завершения загрузки. Связывание необходимо, например, для GC и поиска символов. В ОС фактическое разделение того, что может и не может быть выполнено, является свойством страниц памяти. Это автоматически устанавливается соответствующим образом при загрузке двоичного файла операционной системой. Компилируемые языки JIT могут использовать, например, mprotect для этого.   -  person Dan Robertson    schedule 28.06.2018
comment
Что вы имеете в виду, когда говорите, что для JIT-компиляторов все сложнее? Чем компиляция Common Lisp (fasl или нет) в нативный код отличается от JIT?   -  person Dan Robertson    schedule 20.07.2018
comment
@DanRobertson С JIT вещи существуют в промежуточной форме (байт-код) и скомпилированы. Ко всему прочему, JVM, например, следит за выполнением кода и пытается оптимизировать код на лету (насколько успешно — другой вопрос). Маршрут CL немного более статичен.   -  person mobiuseng    schedule 21.07.2018
comment
конечно, можно было бы рассматривать такой байт-код как fasl. Хотя бы для некоторых реализаций? И разве реализации JavaScript не считаются JIT-компиляторами, даже если они вводят исходный код? Я не знаю, есть ли какой-либо компилятор трассировки CL, но трассировка JIT отличается от JIT в целом.   -  person Dan Robertson    schedule 21.07.2018
comment
@DanRobertson Да, действительно, когда я сказал JIT в этом контексте, я имел в виду отслеживание JIT. Что касается FASL как байт-кода: насколько мне известно, SBCL и CCL создают собственный код, CLISP не имеет JIT. Не уверен насчет ECL, и у меня нет доступа к другим компиляторам.   -  person mobiuseng    schedule 21.07.2018
comment
Насколько я знаю, JVM взяла идею байт-кода из FASL Липса, разница в том, что JVM обрабатывает это самостоятельно, автоматически и как пользователь языка, который вы не должны использовать. В то время как Common Lisp является ручным и открытым для вас.   -  person kisai    schedule 11.11.2019


Ответы (1)


Возможно, это прояснит ситуацию: Группы Google

В отличие от C вы не компилируете свои программы, а затем выполняете их. Вместо этого вы работаете внутри среды lisp. Когда вы загрузили свой файл в sbcl, как указано выше, вы можете просто ввести

(привет)

И ваш код будет выполняться, и код, который вы запускаете, компилируется, а не интерпретируется. В SBCL вам не нужно сначала явно компилировать, так как весь код, который вы вводите или загружаете в sbcl, компилируется на лету. На самом деле интерпретатора в sbcl нет. В других системах lisp вам может потребоваться явная компиляция, чтобы скомпилировать код.

Файл fasl сам по себе не является исполняемым, его необходимо использовать вместе с sbcl.

person hr0m    schedule 20.07.2018
comment
К сожалению, это не так. Это все еще большая картина. Меня интересует механика. Файл FASL должен быть загружен таким образом, чтобы до него мог добраться указатель инструкции. Просто загрузив файл, вы загрузите его в раздел данных, и вы не сможете получить там указатель управления. - person mobiuseng; 21.07.2018
comment
@mobiuseng Нет такой разницы между текстом и данными, когда что-то находится в основной памяти. Возможность выполнения чего-либо определяется битами разрешения в таблице страниц. - person Dan Robertson; 21.07.2018