Система · в работе
Loment VM
Второй способ запустить программу: артефакт можно передать исполнителю, который принимает его по требованию и решает, принимать ли его, читая то, что артефакт уже несёт. Это не более быстрый путь и не способ писать программы легче. Работающий интерпретатор уже есть в репозитории — пакет его не поставляет, и настройка не меняет того, что излучает компилятор.
Что есть и чего нет
Репозиторий теперь несёт рабочий слой интерпретатора, от T0 до T3, читающий ту же промежуточную форму, что и линкер. T0 исполняет эту форму напрямую; T1 записывает профиль обратной связи, не меняя ни байта вывода; T2 декодирует инструкции перед циклом исполнения и работает 6.1× от T0 на корпусе при побайтово том же выводе; компактная сериализация — 28.5% текстовой формы для того же юнита; T3 добавляет специализацию под охраной и путь назад.
Чего нет — так это всего перечисленного в пакете. Интерпретатор — это семейство
tools/lvm.py в репозитории, написанное на Python. Его нет среди бинарников,
которые поставляет релиз, поэтому установленный инструментарий не может запустить программу
этим способом. Настройка тоже не меняет артефакт: сегодня choose vm и
no_vm дают побайтово одинаковый вывод.
Долг, который проект уже носил раньше. Настройка runtime какое-то
время была объявлена в бинарнике, ничего не делая, и позже была доведена до того, что заявляла.
Это та же форма снова: движок есть, поставки нет. Страница говорит, какая половина какая, а не
оставляет читателю выяснять это самому.
Чем оно не является
Три прочтения неверны, и каждое — то, с которым читатель приходит. Они идут впереди проекта, потому что, если сказать их неверно, это превратится в нечто, что пытается делать всё и ничего не делает хорошо.
Не быстрый путь
Наоборот. Нативный путь Loment уже обменивает скорость на независимость, и он не
быстр изначально: против C -O2 на тесте массивов из
docs/212
он идёт в 10.7× позади — это записанное измерение, а не постоянное
обещание. VM — это слой поверх этого. Ось этой линии — не
производительность, а аварийный выход — это вообще другая линия.
Не «написал один раз — запускай где угодно»
Эта задача давно отдана времени компиляции: один IR, три выхода — Linux ELF, Windows PE или автономный объектный файл. Формат байткода не ближе к переносимости, чем это, и заявление проваливает собственный тест: если бы переносимость была целью, критерием было бы «добавление цели не требует нового бэкенда», а целей две.
Не способ писать программы быстрее
Это другой набор вещей, и это не касается ни одной из них: шести прочих поверхностных синтаксисов, форматтера, языкового сервера, определений синтаксиса времени компиляции, руководства, написанного для кодирующих агентов. LVM приходит после того, как программа написана.
Проект в трёх частях
Байткод — не новое изобретение
Это сериализация IR, который компилятор уже испускает. Поставляемый бэкенд — стековая машина: один слот стека на значение SSA, аргументы в стеке, агрегаты через скрытый указатель результата, — так что полная модель выполнения для этого подмножества IR уже существует и уже задействована. Не хватает шага, который её исполняет. LVM был бы четвёртым читателем того же IR: ни нового фронтенда, ни нового IR, ни новой системы типов.
Пятое измерение
choose уже имел четыре: какой слой программа может использовать, как она
возвращает память, может ли артефакт нести runtime и может ли он выходить за свои
пределы. vm — пятое, и оно отвечает для какой модели выполнения
эта программа? Если не написано, это no_vm — то, чем всё было
до появления измерения. С 0.1.4.6 его принимает и выпускная сборка; сегодня это покупает объявление, а не другой артефакт.
Значение говорит ли, а не какой. Это правило, которому уже следует
измерение runtime: то, что внутри, будет меняться годами, и имя,
кодирующее сегодняшнюю ступень, пришлось бы переименовывать, чтобы добавить
завтрашнюю.
Ворота и почему они открылись
До 0.1.4.6 выпускная сборка отвергала choose vm во время
компиляции; принимал его только канал разработки. Правило было грубым — пока не существует
пригодного движка, любой вызов его в выпуске незаконен — чтобы установленный инструментарий
никогда не принимал обещание, которое не может сдержать. Обещание, которое
проваливается, хуже отказа.
0.1.4.6 открывает его, потому что посылка отказа перестала быть верной: первый пригодный движок появился. Теперь настройка — объявление в обоих каналах, и исправление записано, а не удалено — проверка, которая требовала отказа, теперь требует принятия, так что «эти ворота существовали, и вот когда они открылись» остаётся видимым.
Воротам нужно было понятие, которого у репозитория не было: этот компилятор — выпускная сборка или сборка разработки? Проект сводит его к одной константе, одно значение на сторону, переключаемое при упаковке. Одна строка — намеренно: упакованное руководство по языку копируется в дистрибутив без изменений, чтобы «копия в пакете есть копия в репозитории» оставалась проверяемой, и одна строка — наименьший способ согнуть это правило. Цена названа вместе с ним: поставляемое семя компилятора больше не совпадает с репозиторным побайтово, поэтому критерий падает с идентично до воспроизводимо равно, и разница — ровно эта одна константа.
Лестница
Читайте VM как ступени, а не как одну вещь, которую нужно построить. Каждая ступень должна быть достижимой и опровержимой — «написать JIT» не ступень, потому что ничто не может это опровергнуть. Список частей взят у двух систем, сделавших это в масштабе; реализация будет собственной, и останется ли она такой — открытое решение.
T0 — байткод и прямой интерпретатор
Основание. Построено в репозитории. Критерий: программа, запущенная так, даёт побайтово тот же вывод и тот же код возврата, что и нативный артефакт.
T1 — обратная связь
Профили типов, ветвлений и точек вызова. Построено в репозитории. Критерий: профиль попадает в артефакт и третья сторона может его прочитать — а выключение оставляет артефакт побайтово тем же.
T2 — базовый компилятор
Убирает стоимость интерпретации, не оптимизируя. Построено в репозитории — 6.1× от T0 на корпусе. Критерий: измеримо быстрее T0, семантически идентично.
T3 — оптимизирующий компилятор с путём назад
От догадки, оказавшейся неверной, нужно уметь отказаться. Построено в репозитории — для единственной оптимизации, несущей догадку. Это единственный жёсткий критерий на этой ступени: после отказа от догадки результат программы совпадает с нативным артефактом.
T4 — поколенческое и параллельное возвращение памяти
Единственная ступень, не являющаяся продолжением остальных. Дизайн возврата памяти раньше говорил, что здесь это вообще невозможно: бэкенд держал указатели только в локальных переменных и слотах параметров, а это исключает обычный барьер записи. Эта причина больше не действует — появился способ превратить указатель в целое, и поколенческая половина легла на сторону возврата памяти вместе с карточной таблицей и барьером записи. Впереди — сделать это внутри VM, а это другая задача, чем сделать это заранее.
В репозитории есть T0–T3; в пакете нет ни одного. Построить интерпретатор и поставить его в дистрибутиве — два разных шага, и сделан только первый. Ступени выше — форма плана, а не расписание.
Для чего это
Сначала холодный душ: две вещи, которых крупные проекты хотят чаще всего — собираться быстрее, работать быстрее, — обе вне области. Время сборки — проблема внутри компилятора, а время работы — не та ось для этой линии.
Но «крупный» уже обнажил одну проблему, которая структурна, а не дефект, и это единственное, что может её вылечить. Испускаемые символы плоские: сотня модулей означает, что имена функций приходится делать глобально уникальными вручную, а два модуля, каждый из которых определяет одно и то же короткое имя, отвергаются. Это следствие «одной статической линковки» как модели — классическая стена масштабируемости крупного проекта, выдвинутая прямо в лицо пользователю самой структурой языка. Репозиторий уже гоняет корпус чрезмерно крупного проекта как критерий, так что это измерено, а не угадано.
Принятие модуля во время работы
Добавить модуль к нативному артефакту означает передолинковать всю программу. Здесь это означает загрузить единицу.
Замена одного без передолинковки
Измените модуль, перезагрузите его, а остальную программу оставьте где она есть.
Запуск кода, который вы не писали
Стороннее расширение или написанное машиной. Здесь у собственных идей проекта впервые появляется работа. Во время линковки таблица портов, домены возможностей, запись о том, чего нет, и реестр возврата памяти — это аудит: то, что читают после. Во время загрузки они становятся воротами: то, чем решают, прежде чем что-либо запустится.
И это то единственное предложение, за которое эта страница отвечает, и оно опровергаемо: добавление модуля-расширения не означает передолинковку всей программы — и до его загрузки можно сказать, может ли он дотянуться до того, до чего не должен.
На что оно не претендует
Запись о проектировании хранит этот список, и ему место на странице, а не в ней.
Что оно новое
Ничто в нём — не новый кирпич. Свидетельства выполнения, несомые в артефакте и судимые при загрузке, — из 1990-х; отказ загружать то, что нельзя доказать, — так работают песочницы исполнения; один вход с несколькими моделями выполнения — то, что делает самая крупная мобильная среда выполнения. Иначе расположен может быть шов, а не части.
Что никто не делал этих двух вещей
Формулировка повсюду — не найдено поиском, что не то же самое, что не сделано. Два поиска, которые убили бы заявление, записаны как открытые критерии, с честной отметкой, что их не прогоняли исчерпывающе.
Что оно полезно
Сегодня коробка пуста. И третья роль выше опирается на число, которое никто не измерял: какая доля того чрезмерно крупного корпуса — действительно код, который следовало загружать поздно. Если число окажется близко к нулю, роль — просто красивая история.
Где это записано
vm — и запись о том, как эти ворота открылись.
docs/243
T0: байткод — это существующая промежуточная форма, и что значит её исполнять.
docs/259
T2: вынести декодирование из цикла исполнения и критерий, считающий декодирования.
docs/250
Компактная форма: та же форма, 28.5% размера.
docs/261
T3: специализация под охраной и почему деоптимизация на стековой машине дешева.
Дорожная карта
Где VM находится относительно версий — план, заявленный как план.
LomentGC
Лестница возврата памяти — построенная система, для сравнения.
Назад на главную
Что такое Loment и два вида артефактов, которые он собирает.