-
Notifications
You must be signed in to change notification settings - Fork 35
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
Основным циклом программы сделать цикл из RASLFunction::run() #62
Comments
Mazdaywik
added a commit
to bmstu-iu9/simple-refal-distrib
that referenced
this issue
Sep 11, 2016
…ction Последний пункт — первый шаг при выполнении задачи bmstu-iu9/refal-5-lambda#62
Mazdaywik
added a commit
that referenced
this issue
Sep 11, 2016
В сгенерированном коде вместо RefalFunction используется RefalNativeFunction, что позволяет менять базовый класс RefalFunction, не влияя на сгенерированный код.
Mazdaywik
added a commit
to Mazdaywik/mrefal
that referenced
this issue
Sep 11, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 12, 2016
Профилировщик практически полностью переписан в виде машины состояний (хотя многие переходы бессмысленны и бросают исключения). Добавились новые метрики, которые будет использовать Модульный Рефал, последний необходимо будет актуализировать. Да, профилировщик измеряет оверхед, и результат его плачевный. 15 % программы на этот оверхед как раз и уходит. Данную проблему, возможно, удастся решить в рамках задачи #62 (сделать цикл интерпретации основным). Результат профилировки тестовой программы выглядит теперь так: STEP LIMIT REACHED (100000000) … Total program time: 12.625 seconds (100.0 %). (Total refal time): 8.471 seconds (67.1 %). Linear pattern time: 4.719 seconds (37.4 %). Runtime time overhead: 4.154 seconds (32.9 %). Linear result time: 3.752 seconds (29.7 %). Step count 100000000 Memory used 3 nodes, 3 * 16 = 48 bytes Видно, что затраты времени увеличились, новый профилировщик вносит больший оверхед на замеры времени.
Mazdaywik
added a commit
that referenced
this issue
Sep 23, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 23, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 23, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 23, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 25, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 25, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 25, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 25, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 25, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 25, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 25, 2016
Mazdaywik
added a commit
that referenced
this issue
Sep 25, 2016
Код статического ящика описывается как последовательность из 11 команд RASL’а, причём среди них специфических только три: icFetchSwapHead, icFetchSwapInfoBounds и icSwapSave. Эти команды соответствуют функциям initialize_swap_head(), swap_info_bounds() и swap_save(), причём последние две встроены в switch интерпретатора. В refalrts.h упомянутых функций больше нет, функция initialize_swap_head перенесена в пространство имён refalrts::vm.
Mazdaywik
added a commit
to Mazdaywik/mrefal
that referenced
this issue
Oct 9, 2016
…стью Была сделана замена RefalFunction→RefalNativeFunction только в кодогенераторе, однако в библиотечных файлах осталась старая RefalFunction. Кроме того, согласно bmstu-iu9/refal-5-lambda#62, в обобщённом RefalFunction не должно остаться поля указателя, а значит, вызывать из одной функции другую по полю function_info->ptr уже невозможно (см. вызов функции ExitE_).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Изначально Простой Рефал предполагался как компилируемый язык. Каждая функция Рефала компилировалась в аналогичную функцию C++. Семантика рефал-машины реализовывалась непосредственно: в цикле выбиралась очередная функция из поля зрения и вызывалась. Собственно, этот цикл был основным.
Сейчас взят курс на интерпретацию (#48). Уже реализован RASL, реализованы структуры времени выполнения (дескрипторы функций, #46), осталось реализовать двоичное представление и динамический загрузчик (собственно, #48). И теперь при выполнении интерпретируемого кода имеют место два цикла: цикл выбора следующей функции и цикл выполнения инструкций RASL.
Наблюдение: если успешно завершилась функция, написанная на RASL’е (
refalrts::RASLFunction::run()
), то следующая функция, скорее всего, тоже будет написана на RASL’е. Очевидно почему: в RASL обычно компилируются сразу несколько единиц трансляции (например, сейчас — за раз компилируетсяsrefc
,srmake
иlexgen
, за исключением библиотекsrlib
, компилируемых отдельно), либо, даже если только одна, то она содержит несколько функций, которые могут вызывать друг друга. Следствие: вместо завершенияRASLFunction::run()
можно извлекать со стека следующую функцию, и если она тоже написана на RASL’е, перезагружать переменные (указатели на интерпретируемый код и константы) и продолжать выполнение.Слабое место здесь — проверка следующей функции, ибо нужно убедиться, что в поле
node->function_info->ptr
находится именно указатель на&RASLFunction::run
. Но можно изменить представление функций таким образом, чтобы избегать данной проверки. Для этого вrefalrts::RefalFunction
полеptr
с указателем на функцию заменить на указатель на интерпретируемый код. Таким образом, все функции можно будет считать интерпретируемыми:RASLFunction
— уже интерпретируемые, уйдёт избыточное полеptr
, добавится новый опкод, перегружающий поля констант (см. ниже),NativeFunction
, имеющий дополнительное полеptr
, RASL этой функции будет содержать единственную команду — вызвать себя как нативную,RefalSwap
— RASL статического ящика также будет содержать единственную команду «обменять»,RefalEmptyFunction
— RASL содержит единственную команду —refalrts::icFail
.Пояснения тут требует функция
RASLFunction
.RefalFunction
не содержит полей констант, они есть только в наследникеRASLFunction
. В текущей реализацииRASLFunction::run()
в начале извлекаются константы из дескриптора функции, затем происходит выполнение RASL’а. Если будет единый цикл для всей программы, то при переходе к следующей функции на RASL’е потребуется перезагрузка этих полей. Для этого имеет смысл ввести специальную команду, подгружающую новые значения констант из дескриптора.В качестве оптимизации команду перезагрузки можно не добавлять функциям, которые не содержат констант, либо ввести частные команды оптимизации, которые перезагружают только часть полей (только функции, только идентификаторы). Последнее имеет смысл, поскольку, например, гигантские целые используются крайне редко, строки — тоже нечасто. Другая оптимизация: генерировать единые таблицы констант на единицу трансляции, не перезагружать константы в тех локальных функциях, которые вызываются только непосредственно. Но это частности, которые можно сделать позже.
К слову, при таком подходе обретает смысл задача #47 — для статических ящиков использовать не цельную команду, а последовательность команд RASL’а.
При таком подходе функции, полученные прямой кодогенерацией будут выполняться точно также, как и нативные. Нужно будет очень аккуратно организовать профилировщик, чтобы он правильно мерял разные компоненты времени как в режиме интерпретации, так и прямой кодогенерации.
Можно заметить, что ожидаемый результат напоминает архитектуру РЕФАЛа-5. Там аналогично главный цикл программы — цикл выполнения команд RASL’а, для вызова встроенных (≈нативных) функций существует специалный опкод, функции завершаются опкодом, выполняющим переход к следующему шагу. В данном случае это не «слизывание», а результат конвергенции: схожие задачи приводят к схожим решениям.
The text was updated successfully, but these errors were encountered: