Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Вынос дескриптора функции из узла поля зрения #46

Closed
Mazdaywik opened this issue Jul 29, 2016 · 1 comment
Assignees
Labels
Milestone

Comments

@Mazdaywik
Copy link
Member

Mazdaywik commented Jul 29, 2016

Узел поля зрения представляет собой структуру, содержащую ссылки вперёд, назад, тег типа и объединение. Актуальное поле объединения определяется тегом типа. Большинство полей объединения занимают только одно поле, исключение составляют function_info типа refalrts::RefalFunction и swap_info типа refalrts::RefalSwapHead. Первый хранит два поля: указатель на функцию и указатель на её имя (const char*), второй — указатель на следующую голову статического ящика и указатель на имя ящика. Очевидно, в обоих случаях имя используется при печати дампа поля зрения.

Предлагается сделать эти поля указателями на соответствующие объекты. Профит:

  • уменьшение размера узла на 20 % (с точки зрения ОЗУ на современных компьютерах это не интересно, но вот на кэш процессора может повлиять),

  • устранение костыля return refalrts::FnResult(refalrts::cRecognitionImpossible | (__LINE__ << 8)), необходимого для корректной работы с пустыми функциями,

  • упрощение преобразования Простого Рефала в интерпретатор,

  • возможность пополнять дескриптор функции (запись refalrts::RefalFunction) дополнительными полями.

    Что же это за поля?

    • Функции, скомпилированные в режиме интерпретации, выглядят совершенно одинаково: определение нескольких константных статических массивов и вызов функции интерпретации в операторе return. Можно указатели на эти массивы помещать в дескриптор, а в поле указателя на функцию разместить функцию-интерпретатор. Интерпретатор будет анализировать терм конкретизации <Callee …>, находя там себя (Callee) и находя в себе указатели на массивы. В целях экономии памяти (чтобы функции, скомпилированные в режиме прямой кодогенерации не имели избыточных дескрипторов) дескриптор интерпретируемой функции можно унаследовать от общего дескриптора.
    • Поле флагов, может использоваться отладчиком, профилировщиком, рантаймом (зачем-нибудь). Более подробные мысли можно найти в Срастить профилировщик с рантаймом Mazdaywik/mrefal#5.
    • По аналогии с функциями режима интерпретации все статические ящики имеют идентичный код, содержат внутри себя статическую переменную для хранения данных. Статическую переменную можно заменить полем дескриптора.
    • В конце концов пустые функции можно реализовать аналогично функциям режима интерпретации и статическим ящикам — имена у всех будут разные, но указатель на функцию может быть один и тот же (в норме он всё равно не вызывается).

Задача реализуема, и даже реализована, лежит в побочной ветви 4words. Влияние на производительность — ничтожное (замедление где-то 0,5 %…1 %), причём его можно списать на большее число шагов рефал-машины.

@Mazdaywik Mazdaywik added this to the summer 2016 milestone Jul 29, 2016
@Mazdaywik Mazdaywik self-assigned this Jul 29, 2016
@Mazdaywik Mazdaywik added the task label Jul 29, 2016
Mazdaywik added a commit that referenced this issue Aug 12, 2016
Просьба обратить внимание на временной штамп коммита: 13.12.2015.
Правка «мариновалась» в побочной ветке больше полугода (время от времени
пересаживаясь на актуальный master), прежде чем пришло её время.

Из-за того, что Модульный Рефал также должен работать с рантаймом,
пришлось отключить большие куски кода, не используемые этим компилятором.
Вырезаны оказались уточнения термов до функций и АТД, все функции
обновления и переинициализации узлов, refalrts::create_closure,
а также весь интерпретатор.
Mazdaywik added a commit that referenced this issue Aug 12, 2016
Теперь, после перехода на дескрипторы функций, можно
(а) хранить общее тело пустых функций в рантайме,
(б) удалить старый костыль, исправляющий проблему оптимизатором
    компилятора Visual C++ (коммит 7eb13e0 от 07.06.2015).
Mazdaywik added a commit that referenced this issue Aug 12, 2016
Вместо того, чтобы генерировать дескриптор для каждого объявления и определения
локальной функции, окружая его стражами включения, используется специальная
команда #CmdFuncDescr, формируемая в нужных местах в LowLevelRASL.
Mazdaywik added a commit that referenced this issue Aug 12, 2016
В принципе, они могут содержать и мутабельные данные. Например, такими будут
статические ящики, в перспективе возможно добавление поля флагов и т. д.
Mazdaywik added a commit that referenced this issue Aug 12, 2016
)

Дескрипторы этих объектов являются структурами-наследниками структуры
refalrts::RefalFunction. Наследование без виртуальных функций, поскольку
предполагается, что работа будет выполняться всегда с правильным типом
дескриптора (функция refalrts::RefalSwap::run всегда будет вызываться
для RefalSwap и наоборот, дескриптор RefalSwap всегда будет содержать
в поле функции RefalSwap::run).

Поскольку код тела статического ящика вынесен в рантайм, задачу #47 можно
закрывать как невыполнимую.
Mazdaywik added a commit that referenced this issue Aug 12, 2016
Теперь команды #CmdProfileFunction, #CmdIssueMem и #CmdiReserveStack стали
интерпретируемыми. Соответственно, первые две поменяли префикс имени на #Cmdi….

Для последних двух во время выполнения создаётся стек, который пока только
растёт в памяти.
Mazdaywik added a commit that referenced this issue Aug 12, 2016
Получилось немного костыляво, но это исправимо.
Mazdaywik added a commit that referenced this issue Aug 12, 2016
Запуск профилировщика осуществляется явно в функции refalrts::RASLFunction::run,
так время выполнения показывается точнее.
@Mazdaywik
Copy link
Member Author

Задача выполнена, как и предполагалось. Помимо непосредственно генерации дескрипторов для функций, также сделаны особые дескрипторы для пустых функций, статических ящиков и интерпретируемых функций (как и предполагалось в задании). Быстродействие я не измерял, но даже если оно и упало, снижение с лихвой компенсируется возможностью написать полноценный интерпретатор.

P.S. Первоначальный вариант предполагал, что функции описывают дескриптор refalrts::RefalFunction и его наследники, но для ссылок на функции из других единиц трансляции используется только refalrts::RefalFunction. Такой вариант работал в BCC 5.5, GCC (MinGW), CLang, но не работал в Microsoft Visual C++. Чтобы это исправить (fac62b7), пришлось добавить ещё один уровень косвенности: на каждый создаваемый дескриптор указывает ссылка refalrts::RefalFunction&, такие же ссылки импортируются при помощи $EXTERN. Всё вроде работает.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant