Я изучаю методы реализации языков программирования и недавно натолкнулся на стеки спагетти, которые предположительно хорошо подходят для модели стиля передачи продолжения (учитывая их использование, например, в Scheme и SML / NJ ). Для упрощения, давайте рассмотрим только однопоточные процессы для этого вопроса.
Однако меня немного смущает диаграмма в Википедии (также найденная в другом месте ). В частности, я не понимаю, как может возникнуть такая ситуация. Я могу только представить, что серые ветви недоступны и должны быть собраны мусором. С другой стороны, с моим смутным пониманием того, как реализовать CPS с использованием стеков спагетти, я не могу себе представить, как вы могли бы получить цикл в этой структуре. Я должен заключить, что вместо «дерева родительских указателей» это на самом деле ориентированный ациклический граф, с таким количеством источников без мусора, сколько имеется потоков, и с таким количеством приемников, сколько есть (потенциальных) «точек выхода».
Но мое понимание этой реализации довольно расплывчато, так что я, наверное, что-то упустил. Я надеюсь, что кто-то может рассказать мне о «стеках вызовов спагетти», под которыми я подразумеваю структуру данных, используемую в Scheme и / или SML / NJ для реализации процессов на основе CPS.
Учитывая следующий стек вызовов спагетти:
[exit point] <-- ... <-- [frame A] <-- [frame B (active)] ^ `---- [frame C]
Насколько я понимаю, любое управление потоком из B либо раскручивает стек путем перехода к родителю (A становится активным, недостижимый B теперь мусором), либо заменяет активный фрейм подграфом, связанным только с использованием ссылок, содержащихся в B, или ссылок в новые кадры. Выполнение не может перейти к кадру C, что должно означать, что кадр C является мусором.
Вместо предыдущей ситуации я думаю, что может возникнуть следующая ситуация без мусора:
[exit point] <-- ... <-- [frame W] <-- [frame X] <-- [frame Z (active)] ^ | `---- [frame Y] <---´
Например, я могу представить, что кадр Z принадлежит некоторой решающей функции, которая либо продолжается с кадра X, либо с кадра Y (любой из которых вернется к W). Это означает, что стеки вызовов спагетти не являются « деревьями родительских указателей ».
Тем не менее, я не могу представить себе ситуацию, когда цикл может быть построен. Возьмем следующую ситуацию, например:
[exit point] <-- ... <-- [frame P] --> [frame Q (active)] ^ | | v `---- [frame R]
Я знаю, что рекурсивные привязки - вещь, но я очень сомневаюсь, что это разумно. Если Q вернется к R, кадр Q «израсходован». Если R должен был вернуться к P, а P не может просто вернуться к Q, так как он должен быть сначала инициализирован заново. Таким образом, петли могут привести к несовместимым состояниям. (Если, конечно, я неправильно понимаю назначение этой структуры данных, и вы будете использовать только узлы в ней в качестве шаблона для текущего кадра.)
Из этих наблюдений я должен сделать вывод, что стек вызовов спагетти (без мусора) на самом деле является DAG. Это правильно? Или я неправильно понимаю цель этой структуры данных?
Обновления:
Я пролистал копию следующего документа:
Е. А. Хаук и Б. А. Дент. 1968. Механизм стека Берроуза B6500 / B7500. В материалах 30 апреля - 2 мая 1968 г. весенняя совместная компьютерная конференция (AFIPS '68 (весна)). ACM, Нью-Йорк, Нью-Йорк, США, 245-251. DOI = http://dx.doi.org/10.1145/1468075.1468111
Эта статья, кажется, определяет систему стека Suguaro. Как оказалось, эта система стека Suguaro является традиционным стеком вызовов, который позволяет нескольким «заданиям» проходить через кадры частично совместно используемого стека; это абсолютно не связано с продолжениями.
Следующая статья (и сопутствующая статья 1996 г.), по-видимому, объясняет, что происходит в компиляторе SML / NJ:
Чжун Шао и Эндрю У. Аппель. 2000. Эффективное и безопасное преобразование закрытия. ACM Trans. Программа. Lang. Сист. 22, 1 (январь 2000 г.), 129-161. DOI = http://dx.doi.org/10.1145/345099.345125
Я думаю, что я должен прочитать эту статью ( копия на сайте автора ), прежде чем делать что-либо еще с этим вопросом. Концепция «Безопасно связанных замыканий» очень похожа на систему стеков Suguaro, поскольку она всегда очень поверхностна и предназначена только для совместного использования свободных переменных:
В нашем новом алгоритме преобразования замыканий используются надежно связанные замыкания (3-й столбец на рисунке 1), которые содержат только те переменные, которые действительно необходимы в функции, но избегают копирования замыканий путем группировки переменных с одинаковым временем жизни в разделяемую запись. [...] В отличие от связанных замыканий, уровень вложенности надежно связанных замыканий никогда не превышает двух (один слой для самого замыкания, другой для записей с разным временем жизни), поэтому они все еще имеют очень быстрое переменное время доступа.
В документе также явно упоминается, что он не использует «любой стек времени выполнения»:
Вместо этого мы рассматриваем все записи активации как замыкания для функций продолжения и размещаем их в регистрах в куче.
Я думаю, что неправильно понял и / или неправильно прочитал статью в Википедии, так как стеки спагетти не используются для управления потоком. Однако, после внимательного прочтения статей Аппеля и Шао, я, возможно, мог бы переформулировать вопрос со ссылкой на график зависимостей замыканий, а не на «стек вызовов спагетти» (который, очевидно, не является чем-то особенным).