сначала полезное:
про SSA:
одна из лучших книг по теме. к сожалению, не закончена и никогда не будет, но что поделать. (я взял первое попавшееся зеркало, в принципе — поиск по Inria SSA book). вот
готовые pdf.
SoN — это Sea of Nodes. искать по Cliff Click, Sea of Nodes. обязательно найдётся тезис и куча более мелких бумажек-разъяснений. очень интересная идея: IR-ноды плавают в «первичном бульоне» без определённого порядка, связаные только зависимостями данных. в список для кодогена выстраиваются на одном из последних этапов. позволяет обойтись без CFG, упрощает DFA, имеет VRP в виде type lattices. (да, специально. прошу прощения. рассчитываю на любопытство, которое толкнёт искать расшифровки этих матов.) придумано не сильно позже SSA, но со свистом пролетело мимо academia: это вам не межделмаш, кто такой ваще этот Клиф Клик?
на самом деле это всё действительно очень-очень просто. серьёзно, не надо пугаться: не боги компиляторы обжигают.
а теперь можно и водой заняться. %-)
Михаил писал(а):
Ormcode первый опыт написания компилятора.
о-о-о. welcome to the club. если понравилось — есть опасность получить бесполезное, но очень увлекательное хобби. я так и влип.
Михаил писал(а):
Ещё из неприятного, 64 - максимальное количество методов, включая наследников.
а зачем ограничивать размер VMT? вот глубину наследования — это понятно, чтобы проверка типа в рантайме за O(1). но VMT-то зачем? (я не издеваюсь и не иронизирую, если что. просто тон такой, заранее прошу прощения.)
Михаил писал(а):
Ещё с деревьями взаимная не любовь.
как перестать беспокоиться и полюбить балансированые двоичные деревья. %-)
Михаил писал(а):
Долой деревья и списки. Да здравствуют линейные массивы
на самом деле в очень многих случаях это правильное решение. если вдобавок массив возможно отсортировать и использовать на нём двоичный поиск — то отличная структура данных, быстрая и удобная. если в среднем несколько десятков элементов, то список — самое то: обычно нет смысла на таких размерах заморачиваться деревьями или хэш-табличками.
Михаил писал(а):
Константы, списки импорта, таблицы методов жестко зашиты в исполняемый код )))
ну и пусть. подумаешь. со временем придёт понимание, где хардкод нормально, а где надо оставить запас для расширения. я довольно часто прибиваю всё гвоздями изначально, а потом меняю, если надо.
Михаил писал(а):
Время следующего срабатывания стал править на основе очереди ожидания. И вот этот вариант постоянно глючил. Единственно не использовал fd. Linux не ‘родная’ для меня система. Сработал стереотип, что файлы это нечто лежащее на диске и крайне ненадежное.
юникс же. «всё на свете файл». ну, то есть, всё, что можно — имеет fd. и в большинстве случаев на это можно натравить select. а, кстати, как раз на файлы и нельзя: бесполезно. казалось бы: для файлового дескриптора самое то делать асинхронный ввод-вывод, ожидая окончания операции через select… а вот шиш.
у X11 же можно получить сокетный fd, и спокойно ожидать на нём событий. а потом звать xlib, пусть что-то с этим сделает. очень удобно, всегда так пишу.
кстати, если всё многопоточное — искренне советую жёстко прибить всю работу с оконной системой к одному потоку, и всё-всё делать только в нём. будет значительно меньше проблем. можно поверх этого сделать свою внутреннюю шину сообщений и общаться через неё — а нижний слой пусть отдельно. и для шинды я бы рекомендовал эмулировать идеологию иксов: из колбэков просто постить события в шину, а обрабатывать их в общем цикле. так и код делать проще, и получается всё более-менее единообразно.
btw: не рекомендую заморачиваться с xcb. ну какой смысл работать с иксовым протоколом на уровне протокола? xlib, конечно, не лучший интерфейс — но вполне удовлетворительный. только не надо всё размазывать по потокам.
Михаил писал(а):
В защиту risc. Во первых Ваша цитата от 20 августа 23 года, 23 страница. Немного выдернута из контекста, но смысл вроде верный:
вот в этом и проблема с блогозапиями (потому что там, по сути, блог): без расшифровки не всегда понятно, что автор имел в виду. там было несколько идей в одной, на самом деле: «абстрактрый риск с преобразованием его кода обратно в SSA для JIT», «абстрактный риск с бесконечными регистрами (почти SSA)» и «абстрактный риск и виртуальная машина, а JIT когда-нибудь потом».
есть простой способ решения проблемы с выделением регистров: backward linear scan. этап первый: код для рисков с фиксированым количеством регистров переписываем в SSA. это тривиально делается в один проход. с фита-нодами не паримся, просто расставляем метки для переходов. этап второй: идём по коду начиная с
последней инструкции, назначая регистры в процессе. это можно (и нужно) совместить непосредственно с кодогенерацией. получается так: когда инструкции нужны операнды — мы смотрим, из каких команд они пришли (это всегда однозначно, указатели можно проставить в процессе создания SSA), выделяем свободные регистры, прописываем в инструкции-источники указание: «результат положи конкретно в этот регистр!» таким образом когда мы доходим до какой-то инструкции, то мы уже знаем, что в какие регистры положить. если регистров не хватает — делаем spill. в общем, это надо один раз нарисовать на нескольких примерах — и в голове щёлкнет Озарение. код получается довольно приличный, процесс очень быстрый и однопроходный. NanoJIT в Oberon/Ur делает именно так.
ах, да. метки — это implicit phi nodes. когда встречаем метку — то простейшим вариантом будет просто спильнуть все регистры. если хочется чуть лучше — можно мержить регистровые картинки.
большой недостаток метода: он очень плохо выделяет регистры для циклов. то есть, он в принципе очень плохо работает с переходами вверх по коду — а это, к сожалению, как раз циклы.
Михаил писал(а):
Все sym файлы, уже содержат позиционно независимый код - PIC, так как ссылки разрешаются на этапе компиляции. Загрузчик для разрешения ссылок не требуется.
не понял. требуется как минимум для правки call destinations при обращении к процедурам в других модулях.
(p.s.: «В жертву принесена раздельная компиляция». упс. это я как-то пропустил.)Михаил писал(а):
JIT превратился в простой конвертор и состоит из одного большого CASE - даже оптимизаций никаких не делал. Скорость потрясающая, доли процента от времени загрузки.
нормальный подход. осталось сделать IR на базе SSA и линейный аллокатор регистров. %-)
Михаил писал(а):
Понял одно. Стоит написать один и уже не остановиться.
ага. у меня та ж фигня. %-)
p.p.s: «Время следующего срабатывания стал править на основе очереди ожидания.» — не надо в таймере хранить таймаут (если я верно понял). надо хранить как раз время срабатывания, в системных тиках, например. тогда ничего править вообще не надо, надо только пробежаться по списку таймеров. у кого время срабатывания <= текущему значению системных тиков — стреляем. из остального выбираем минимальное значение — и вот нам готовый минимально возможный таймаут.