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

Компилятор вылетает при самоприменении #319

Closed
Mazdaywik opened this issue Jul 16, 2020 · 41 comments · Fixed by #328
Closed

Компилятор вылетает при самоприменении #319

Mazdaywik opened this issue Jul 16, 2020 · 41 comments · Fixed by #328
Assignees
Labels

Comments

@Mazdaywik
Copy link
Member

При самоприменении в режиме RLMAKE_FLAGS=-X-OADS компилятор упал.

Выяснилось, что проблема в неверном порождении кода специализированной функции. Запуск

set RLMAKE_FLAGS=-X-OADS -X--log=__log.txt

выявил в логе следующее:

  PutRASLCommands\1@1 {
    s.FileHandle0#1 (CmdSentence e.SubCommands#2)
      = <Putout s.FileHandle0#1 '    (CmdSentence'>
        <PutRASLCommands@4 s.X#0 (e.X#0) e.X0#0>
        <Putout s.FileHandle0#1 '    )  // CmdSentence'>;

В правой части появляются переменные s.X#0, e.X#0 и e.X0#0, которых нет в левой части. При генерации RASL’а для этой функции компилятор падает.

Переменные с индексами X порождаются в специализаторе:

NameSignatureVars-Term {
(e.KnownVars) (TkVariable s.Mode)
= <NewVarName (e.KnownVars) s.Mode 'X' 0> : (e.KnownVars^) e.Index
= (e.KnownVars)
(TkVariable e.Index);

Удалось построить небольшой тест, воспроизводящий проблему:

$ENTRY PutProgramElement {
  e.Stars = <F () e.Stars>;
}

$SPEC F (e.LEFT) e.RIGHT;

F {
  (e.Left) e.Right = <G (e.Left) e.Right>;
}

$SPEC G (e.LEFT) e.right;

G {
  (e.Left) '*' e.Right = <F (e.Left '*') e.Right>;
  (e.Left) /* empty */ = /* empty */;
}

В логе для теста:

  G@2 {
    (e.Left0#1) '*' e.Right#1 = <F@2 (e.X#0) e.X0#0>;
@Mazdaywik Mazdaywik added the bug label Jul 16, 2020
Mazdaywik added a commit that referenced this issue Jul 18, 2020
• Уточнён тип переменной-флага e.NeedRelationCheck → s.NeedRelationCheck.
• Мелкие стилевые исправления.
Mazdaywik added a commit that referenced this issue Jul 18, 2020
Ошибка, выявленная самоприменением, исправлена. Оказалось, что это была
простая опечатка.
@Mazdaywik

This comment has been minimized.

Mazdaywik added a commit that referenced this issue Jul 18, 2020
Когда обнаруживалось зацикливание по Хигману-Крускалу, после построения
обобщённого вызова не восстанавливались вызовы в нём — оставались заглушки
e.Call.
@Mazdaywik

This comment has been minimized.

Mazdaywik added a commit that referenced this issue Jul 18, 2020
Функция DoUnEscapeString-SR содержит аккумулятор, а из-за обобщения
снизу этот аккумулятор специализируется для случаев каждого экранированного
символа в нём. Это даёт визуальную задержку компиляции на маленьком файле.
Поэтому данная функция помечена специализируемой без статических параметров —
любой её вызов будет тривиальным.
@Mazdaywik
Copy link
Member Author

Теперь компилятор успешно самоприменяется с -OADS:

Total program time: 1039.60900 seconds (100.0 %).
(Total refal time): 948.56900 seconds (91.2 %).
t- and e-var copy time: 510.66200 seconds (49.1 %).
Linear result time: 174.14500 seconds (16.8 %).
Linear pattern time: 161.38300 seconds (15.5 %).
Open e-loop time (clear): 50.62100 seconds (4.9 %).
Native time: 34.25100 seconds (3.3 %).
Context copy time: 29.03900 seconds (2.8 %).
Runtime time overhead: 27.75000 seconds (2.7 %).
Repeated e-var match time (outside e-loops): 27.19100 seconds (2.6 %).
Repeated e-var match time (inside e-loops): 12.21200 seconds (1.2 %).
Repeated t-var match time (inside e-loops): 11.94900 seconds (1.1 %).
Repeated t-var match time (outside e-loops): 0.40600 seconds (0.0 %).
Step count 475956958
Identifiers allocated: 2335
Memory used 12557000 nodes, 12557000 * 16 = 200912000 bytes

Повторный прогон даёт такой результат:

Total program time: 599.17200 seconds (100.0 %).
(Total refal time): 553.90100 seconds (92.4 %).
t- and e-var copy time: 202.28200 seconds (33.8 %).
Linear pattern time: 133.73400 seconds (22.3 %).
Linear result time: 120.81100 seconds (20.2 %).
Open e-loop time (clear): 49.05100 seconds (8.2 %).
Native time: 26.63000 seconds (4.4 %).
Repeated e-var match time (outside e-loops): 26.26200 seconds (4.4 %).
Runtime time overhead: 16.51600 seconds (2.8 %).
Repeated e-var match time (inside e-loops): 11.03400 seconds (1.8 %).
Repeated t-var match time (inside e-loops): 10.46100 seconds (1.7 %).
Context copy time: 2.12500 seconds (0.4 %).
Repeated t-var match time (outside e-loops): 0.26600 seconds (0.0 %).
Step count 296905888
Identifiers allocated: 2335
Memory used 12556000 nodes, 12556000 * 16 = 200896000 bytes

Т.е. ускорение примерно в 2 раза. Но пока ещё рано оценивать быстродействие, впереди ещё много работы (#310).

@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

Mazdaywik added a commit that referenced this issue Nov 14, 2020
Ошибка была внесена при рефакторинге (#310), не учитывались холодные
скобки вызова. Ошибка была обнаружена при попытке самоприменить
компилятор с ключами -OiADS, поэтому ссылка на #319.
@Mazdaywik
Copy link
Member Author

Обнаружилось несколько новых проблем. Обнаружились и падения, и зацикливания специализатора. Для диагностики были отдельно прокомпилированы все исходники с сохранением дампа и лога:

for %r in (*.ref) do call ..\..\bin\rlc -OiADS --opt-tree-cycles=300 --log=__log-%~nr.log %r -C 2>__err-%~nr.txt

Проблемы опишу в комментариях ниже. По мере устранения проблем эти комментарии я скрою.

@Mazdaywik
Copy link
Member Author

Слишком много проходов оптимизации

Как видно из команды выше, выполнялось 300 проходов оптимизации. Такой выбор числа проходов позволил оценить, на каком количестве файлов компиляция не завершилась за 100 и за 200 проходов.

Более 200 проходов:

D:\…\src\compiler>bash -c "grep 'Pass 99' *.log"
__log-Log.log:Sat Nov 14 09:49:00 2020: AST of file Pass 99 (before Spec):

Более 100 проходов:

D:\…\src\compiler>bash -c "grep 'Pass 199' *.log"
__log-Checker.log:Sat Nov 14 08:52:28 2020: AST of file Pass 199 (before Drive):
__log-Checker-Screening.log:Sat Nov 14 08:51:15 2020: AST of file Pass 199 (before Drive):
__log-Desugaring.log:Sat Nov 14 08:57:19 2020: AST of file Pass 199 (before Drive):
__log-Log-AST.log:Sat Nov 14 09:41:20 2020: AST of file Pass 199 (before Drive):
__log-Log.log:Sat Nov 14 09:48:01 2020: AST of file Pass 199 (before Spec):
__log-main.log:Sat Nov 14 09:52:03 2020: AST of file Pass 199 (before Drive):
__log-OptTree-Drive.log:Sat Nov 14 09:53:36 2020: AST of file Pass 199 (before Drive):

Значит, нужно разбираться, а что так много.

@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

Mazdaywik added a commit that referenced this issue Nov 15, 2020
Не проверялся случай, когда и старая, и новая сигнатуры начинаются с идентичного
терма, не являющегося скобкой — общий терм нужно было стирать.
@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

Mazdaywik added a commit that referenced this issue Nov 22, 2020
Было заманчиво написать

    <ApplyInlines e.Inlines (e.Inlines)>

и сделать функцию MakeInlineClosure с одним аргументом, но это оказалось
немного медленнее. Поэтому там e.InlinesAcc, который насыщается
до неподвижной точки.
@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

@Mazdaywik

This comment has been minimized.

Mazdaywik added a commit that referenced this issue Nov 25, 2020
Функция StrFromMacroDigit переименована в Symb-Digit по аналогии
с Add-Digits и другими. Автотест добавлен для уверенности — для покрытия
нового первого предложения функции (ранее тесты проверяли только длинные
числа).
@Mazdaywik

This comment has been minimized.

@Mazdaywik
Copy link
Member Author

Мне удалось скомпилировать компилятор с ключами

set RLMAKE_FLAGS=-X-OdiADGPRS -X--opt-tree-cycles=300
set SCRIPT_FLAGS=--scratch --debug
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
rlc-core.exe.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\exe\library.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch\exe\hash.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\exe\refalrts-main.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\refalrts.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\refalrts-vm-api.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\platform-windows\refalrts-platform-specific.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\debug\refalrts-diagnostic-initializer.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\debug\refalrts-debugger.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\refalrts-dynamic.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\refalrts-functions.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\refalrts-vm.cpp:
d:\mazdaywik\documents\refal-5-lambda\lib\scratch-rt\debug\refalrts-profiler.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
** Compilation succeeded **

Почему не получалось раньше — не знаю. Вообще, странностей что-то много последнее время…

Mazdaywik added a commit that referenced this issue Nov 27, 2020
Почему-то (видимо, невнимательный копипаст) все функции программы помещались
в список e.Forbidden, из-за чего они не прогонялись.
@Mazdaywik
Copy link
Member Author

Новая, интересная ошибка

Из-за предыдущего коммита перестала работать прогонка. Сейчас заработала. Попробовал собрать компилятор с ключами

set RLMAKE_FLAGS=-X-OdiADGPRS -X--opt-tree-cycles=300
set SCRIPT_FLAGS=--scratch --debug

Сначала не хватило памяти на самоприменение. Поднял порог:

memory-limit = 75000000

Программа откомпилировалась, но компилятор в ней нашёл ошибки. Новые, интересные ошибки:

static refalrts::FnResult func_gen_Configm_GetCppCompiler_D2(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
  (void) vm;
  refalrts::this_is_generated_function(vm);
  refalrts::RefalFunction **functions;
  const refalrts::RefalIdentifier *identifiers;
…
static refalrts::NativeReference nat_ref_gen_Configm_GetCppCompiler_D2("Config-GetCppCompiler*2", COOKIE1_, COOKIE2_, func_gen_Configm_GetCppCompiler_D2);
…
static refalrts::FnResult func_gen_Configm_GetCppCompiler_D2(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
  (void) vm;
  refalrts::this_is_generated_function(vm);
  refalrts::RefalFunction **functions;
  const refalrts::RefalIdentifier *identifiers;
…
static refalrts::NativeReference nat_ref_gen_Configm_GetCppCompiler_D2("Config-GetCppCompiler*2", 0U, 0U, func_gen_Configm_GetCppCompiler_D2);

Т.е. функция определена дважды. Один раз как entry, второй — как локальная. И эта функция — функция-хвост.

Полный список продублированных функций
rlc-core.exe.cpp: In function 'refalrts::FnResult func_gen_Configm_GetCppCompiler_D2(refalrts::VM*, refalrts::Iter, refalrts::Iter)':
rlc-core.exe.cpp:1218524:27: error: redefinition of 'refalrts::FnResult func_gen_Configm_GetCppCompiler_D2(refalrts::VM*, refalrts::Iter, refalrts::Iter)'
 static refalrts::FnResult func_gen_Configm_GetCppCompiler_D2(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp:555679:27: error: 'refalrts::FnResult func_gen_Configm_GetCppCompiler_D2(refalrts::VM*, refalrts::Iter, refalrts::Iter)' previously defined here
 static refalrts::FnResult func_gen_Configm_GetCppCompiler_D2(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp: At global scope:
rlc-core.exe.cpp:1218681:71: error: redefinition of 'refalrts::NativeReference nat_ref_gen_Configm_GetCppCompiler_D2'
 static refalrts::NativeReference nat_ref_gen_Configm_GetCppCompiler_D2("Config-GetCppCompiler*2", 0U, 0U, func_gen_Configm_GetCppCompiler_D2);
                                                                       ^
rlc-core.exe.cpp:555836:34: error: 'refalrts::NativeReference nat_ref_gen_Configm_GetCppCompiler_D2' previously declared here
 static refalrts::NativeReference nat_ref_gen_Configm_GetCppCompiler_D2("Config-GetCppCompiler*2", COOKIE1_, COOKIE2_, func_gen_Configm_GetCppCompiler_D2);
                                  ^
rlc-core.exe.cpp: In function 'refalrts::FnResult func_gen_Configm_SetCppCompiler_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)':
rlc-core.exe.cpp:1218684:27: error: redefinition of 'refalrts::FnResult func_gen_Configm_SetCppCompiler_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)'
 static refalrts::FnResult func_gen_Configm_SetCppCompiler_D1(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp:794282:27: error: 'refalrts::FnResult func_gen_Configm_SetCppCompiler_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)' previously defined here
 static refalrts::FnResult func_gen_Configm_SetCppCompiler_D1(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp: At global scope:
rlc-core.exe.cpp:1218761:71: error: redefinition of 'refalrts::NativeReference nat_ref_gen_Configm_SetCppCompiler_D1'
 static refalrts::NativeReference nat_ref_gen_Configm_SetCppCompiler_D1("Config-SetCppCompiler*1", 0U, 0U, func_gen_Configm_SetCppCompiler_D1);
                                                                       ^
rlc-core.exe.cpp:794359:34: error: 'refalrts::NativeReference nat_ref_gen_Configm_SetCppCompiler_D1' previously declared here
 static refalrts::NativeReference nat_ref_gen_Configm_SetCppCompiler_D1("Config-SetCppCompiler*1", COOKIE1_, COOKIE2_, func_gen_Configm_SetCppCompiler_D1);
                                  ^
rlc-core.exe.cpp: In function 'refalrts::FnResult func_gen_Configm_SetErrorFile_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)':
rlc-core.exe.cpp:1218764:27: error: redefinition of 'refalrts::FnResult func_gen_Configm_SetErrorFile_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)'
 static refalrts::FnResult func_gen_Configm_SetErrorFile_D1(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp:794362:27: error: 'refalrts::FnResult func_gen_Configm_SetErrorFile_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)' previously defined here
 static refalrts::FnResult func_gen_Configm_SetErrorFile_D1(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp: At global scope:
rlc-core.exe.cpp:1218826:69: error: redefinition of 'refalrts::NativeReference nat_ref_gen_Configm_SetErrorFile_D1'
 static refalrts::NativeReference nat_ref_gen_Configm_SetErrorFile_D1("Config-SetErrorFile*1", 0U, 0U, func_gen_Configm_SetErrorFile_D1);
                                                                     ^
rlc-core.exe.cpp:794424:34: error: 'refalrts::NativeReference nat_ref_gen_Configm_SetErrorFile_D1' previously declared here
 static refalrts::NativeReference nat_ref_gen_Configm_SetErrorFile_D1("Config-SetErrorFile*1", COOKIE1_, COOKIE2_, func_gen_Configm_SetErrorFile_D1);
                                  ^
rlc-core.exe.cpp: In function 'refalrts::FnResult func_gen_Configm_SetTargetSuffix_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)':
rlc-core.exe.cpp:1218829:27: error: redefinition of 'refalrts::FnResult func_gen_Configm_SetTargetSuffix_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)'
 static refalrts::FnResult func_gen_Configm_SetTargetSuffix_D1(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp:794427:27: error: 'refalrts::FnResult func_gen_Configm_SetTargetSuffix_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)' previously defined here
 static refalrts::FnResult func_gen_Configm_SetTargetSuffix_D1(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp: At global scope:
rlc-core.exe.cpp:1218912:72: error: redefinition of 'refalrts::NativeReference nat_ref_gen_Configm_SetTargetSuffix_D1'
 static refalrts::NativeReference nat_ref_gen_Configm_SetTargetSuffix_D1("Config-SetTargetSuffix*1", 0U, 0U, func_gen_Configm_SetTargetSuffix_D1);
                                                                        ^
rlc-core.exe.cpp:794510:34: error: 'refalrts::NativeReference nat_ref_gen_Configm_SetTargetSuffix_D1' previously declared here
 static refalrts::NativeReference nat_ref_gen_Configm_SetTargetSuffix_D1("Config-SetTargetSuffix*1", COOKIE1_, COOKIE2_, func_gen_Configm_SetTargetSuffix_D1);
                                  ^
rlc-core.exe.cpp: In function 'refalrts::FnResult func_gen_Configm_SetCppCompilerSuf_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)':
rlc-core.exe.cpp:1218915:27: error: redefinition of 'refalrts::FnResult func_gen_Configm_SetCppCompilerSuf_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)'
 static refalrts::FnResult func_gen_Configm_SetCppCompilerSuf_D1(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp:794513:27: error: 'refalrts::FnResult func_gen_Configm_SetCppCompilerSuf_D1(refalrts::VM*, refalrts::Iter, refalrts::Iter)' previously defined here
 static refalrts::FnResult func_gen_Configm_SetCppCompilerSuf_D1(refalrts::VM *vm, refalrts::Iter arg_begin, refalrts::Iter arg_end) {
                           ^
rlc-core.exe.cpp: At global scope:
rlc-core.exe.cpp:1219006:74: error: redefinition of 'refalrts::NativeReference nat_ref_gen_Configm_SetCppCompilerSuf_D1'
 static refalrts::NativeReference nat_ref_gen_Configm_SetCppCompilerSuf_D1("Config-SetCppCompilerSuf*1", 0U, 0U, func_gen_Configm_SetCppCompilerSuf_D1);
                                                                          ^
rlc-core.exe.cpp:794604:34: error: 'refalrts::NativeReference nat_ref_gen_Configm_SetCppCompilerSuf_D1' previously declared here
 static refalrts::NativeReference nat_ref_gen_Configm_SetCppCompilerSuf_D1("Config-SetCppCompilerSuf*1", COOKIE1_, COOKIE2_, func_gen_Configm_SetCppCompilerSuf_D1);
                                  ^

Обращает на себя внимание то, что всё это — хвосты, и одно вхождение определено как entry, а второе — как локальное:

Выборка только NativeReference
 static refalrts::NativeReference nat_ref_gen_Configm_GetCppCompiler_D2("Config-GetCppCompiler*2", 0U, 0U, func_gen_Configm_GetCppCompiler_D2);
 static refalrts::NativeReference nat_ref_gen_Configm_GetCppCompiler_D2("Config-GetCppCompiler*2", COOKIE1_, COOKIE2_, func_gen_Configm_GetCppCompiler_D2);
 static refalrts::NativeReference nat_ref_gen_Configm_SetCppCompiler_D1("Config-SetCppCompiler*1", 0U, 0U, func_gen_Configm_SetCppCompiler_D1);
 static refalrts::NativeReference nat_ref_gen_Configm_SetCppCompiler_D1("Config-SetCppCompiler*1", COOKIE1_, COOKIE2_, func_gen_Configm_SetCppCompiler_D1);
 static refalrts::NativeReference nat_ref_gen_Configm_SetErrorFile_D1("Config-SetErrorFile*1", 0U, 0U, func_gen_Configm_SetErrorFile_D1);
 static refalrts::NativeReference nat_ref_gen_Configm_SetErrorFile_D1("Config-SetErrorFile*1", COOKIE1_, COOKIE2_, func_gen_Configm_SetErrorFile_D1);
 static refalrts::NativeReference nat_ref_gen_Configm_SetTargetSuffix_D1("Config-SetTargetSuffix*1", 0U, 0U, func_gen_Configm_SetTargetSuffix_D1);
 static refalrts::NativeReference nat_ref_gen_Configm_SetTargetSuffix_D1("Config-SetTargetSuffix*1", COOKIE1_, COOKIE2_, func_gen_Configm_SetTargetSuffix_D1);
 static refalrts::NativeReference nat_ref_gen_Configm_SetCppCompilerSuf_D1("Config-SetCppCompilerSuf*1", 0U, 0U, func_gen_Configm_SetCppCompilerSuf_D1);
 static refalrts::NativeReference nat_ref_gen_Configm_SetCppCompilerSuf_D1("Config-SetCppCompilerSuf*1", COOKIE1_, COOKIE2_, func_gen_Configm_SetCppCompilerSuf_D1);

И это странно: функции-хвосты всегда должны быть локальными.

@Mazdaywik
Copy link
Member Author

Ошибка из предыдущего комментария исправлена. Вылезла другая, знакомая ошибка:

Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Fatal: Error detected (LME2053)
Fatal: Error detected (LME1642)
Fatal: Error detected (LME1577)
Fatal: Error detected (LME1657)
Fatal: Access violation.  Link terminated.

@Mazdaywik
Copy link
Member Author

Mazdaywik commented Nov 28, 2020

Формально разбил длинный файл на два куска примерно равной длины (по 600 000 строк), откомпилировалось:

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
hash.cpp:
library.cpp:
refalrts.cpp:
refalrts-diagnostic-initializer.cpp:
refalrts-dynamic.cpp:
refalrts-functions.cpp:
refalrts-main.cpp:
refalrts-profiler.cpp:
refalrts-vm.cpp:
refalrts-vm-api.cpp:
rlc-core.exe-1.cpp:
rlc-core.exe-2.cpp:
d:\mazdaywik\documents\refal-5-lambda\src\lib\platform-windows\refalrts-platform-specific.cpp:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

Значит, или компоновщик не осиливает объектник такой длины, или компилятор его некорректно создаёт. Всё-таки надо чистить программу от избыточных функций.

@Mazdaywik
Copy link
Member Author

Mazdaywik commented Nov 29, 2020

Программа от избыточных функций чистится: e389bec, dc64eec. Но это не помогло особо:

Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Fatal: Error detected (LME2053)
Fatal: Error detected (LME1642)
Fatal: Error detected (LME1577)
Fatal: Error detected (LME1657)
Fatal: Access violation.  Link terminated.

Длина файла rlc-core.exe.cpp, куда скомпилировался весь компилятор, составляет теперь 955 990 строк. Ранее было ≈1,2 млн (не сохранил точное значение). Да, это существенно меньше. Но недостаточно.


Было сделано два замера:

  • set SCRIPT_FLAGS=--scratch --debug
    set RLMAKE_FLAGS=-X-OdPR -X--opt-tree-cycles=300
  • set SCRIPT_FLAGS=--scratch --debug
    set RLMAKE_FLAGS=-X-OdiADPRS -X--opt-tree-cycles=300

В обоих случаях измерялся объём файлов *.cpp в каталоге build/compiler, за исключением исходников рантайма и библиотек Library.cpp и Hash.cpp. Получилась вот такая картина:

image

Колонка B — размеры файлов первого замера (байты), D — второго. Колонки C и E — доля размеров файлов в общей сумме. Колонка G — величина распухания, G = D / B. Строка 45 — суммарный размер в мегабайтах.

Выводы:

  • Больше всего по объёму оптимизированный файл OptTree-Drive.cpp, его размер 3 551 383 байта, относительный размер 9,7 %. Он же сравнительно сильно распух — в ≈3 раза (304 %).
  • Вслед за ним идёт Desugaring.ref — 2 795 094 байт или 7,6 %. Распух в ≈4 раза (376 %).
  • Сильнее всего распух в относительном выражении Generator-Native.cpp: в ≈5 раз (481 %). Он же занимает третье место: 2 180 928 или 6,0 %.
  • Среднее распухание — примерно в 2 раза (225 %).

Просмотр файла OptTree-Drive.cpp показывает нам вот что:

find "static refalrts::NativeReference" < OptTree-Drive.cpp | sort
Много строчек
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z1("DriveInlineOptimizerTick=2@1", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z1);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z10("DriveInlineOptimizerTick=2@10", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z10);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z11("DriveInlineOptimizerTick=2@11", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z11);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z12("DriveInlineOptimizerTick=2@12", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z12);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z13("DriveInlineOptimizerTick=2@13", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z13);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z14("DriveInlineOptimizerTick=2@14", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z14);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z15("DriveInlineOptimizerTick=2@15", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z15);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z16("DriveInlineOptimizerTick=2@16", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z16);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z2("DriveInlineOptimizerTick=2@2", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z2);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z3("DriveInlineOptimizerTick=2@3", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z3);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z4("DriveInlineOptimizerTick=2@4", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z4);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z5("DriveInlineOptimizerTick=2@5", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z5);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z6("DriveInlineOptimizerTick=2@6", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z6);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z7("DriveInlineOptimizerTick=2@7", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z7);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z8("DriveInlineOptimizerTick=2@8", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z8);
static refalrts::NativeReference nat_ref_gen_DriveInlineOptimizerTick_A2Z9("DriveInlineOptimizerTick=2@9", COOKIE1_, COOKIE2_, func_gen_DriveInlineOptimizerTick_A2Z9);
…
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z1("OptSentence$1:1@1", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z1);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z10("OptSentence$1:1@10", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z10);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z11("OptSentence$1:1@11", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z11);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z12("OptSentence$1:1@12", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z12);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z13("OptSentence$1:1@13", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z13);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z14("OptSentence$1:1@14", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z14);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z15("OptSentence$1:1@15", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z15);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z16("OptSentence$1:1@16", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z16);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z2("OptSentence$1:1@2", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z2);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z3("OptSentence$1:1@3", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z3);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z4("OptSentence$1:1@4", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z4);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z5("OptSentence$1:1@5", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z5);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z6("OptSentence$1:1@6", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z6);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z7("OptSentence$1:1@7", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z7);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z8("OptSentence$1:1@8", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z8);
static refalrts::NativeReference nat_ref_gen_OptSentence_S1B1Z9("OptSentence$1:1@9", COOKIE1_, COOKIE2_, func_gen_OptSentence_S1B1Z9);
…
static refalrts::NativeReference nat_ref_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1("DoOptSentence-MakeSubstitutions-Intrinsic$2=2:1", COOKIE1_, COOKIE2_, func_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1);
static refalrts::NativeReference nat_ref_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1Z1("DoOptSentence-MakeSubstitutions-Intrinsic$2=2:1@1", COOKIE1_, COOKIE2_, func_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1Z1);
static refalrts::NativeReference nat_ref_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1Z2("DoOptSentence-MakeSubstitutions-Intrinsic$2=2:1@2", COOKIE1_, COOKIE2_, func_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1Z2);
static refalrts::NativeReference nat_ref_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1Z3("DoOptSentence-MakeSubstitutions-Intrinsic$2=2:1@3", COOKIE1_, COOKIE2_, func_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1Z3);
static refalrts::NativeReference nat_ref_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1Z4("DoOptSentence-MakeSubstitutions-Intrinsic$2=2:1@4", COOKIE1_, COOKIE2_, func_gen_DoOptSentencem_MakeSubstitutionsm_Intrinsic_S2A2B1Z4);

Похоже, имеет место некая специализация по флагам. Но это нужно лог изучать.

Аналогичный просмотр Desugaring.cpp показывает следующее

Похоже, опять какая-то переспециализация по аккумулятору
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A1("EnumerateVars-Assignments$2=1", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A1);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A1Z1("EnumerateVars-Assignments$2=1@1", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A1Z1);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A1Z2("EnumerateVars-Assignments$2=1@2", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A1Z2);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A1Z3("EnumerateVars-Assignments$2=1@3", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A1Z3);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A1Z4("EnumerateVars-Assignments$2=1@4", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A1Z4);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2("EnumerateVars-Assignments$2=2", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z1("EnumerateVars-Assignments$2=2@1", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z1);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z10("EnumerateVars-Assignments$2=2@10", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z10);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z11("EnumerateVars-Assignments$2=2@11", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z11);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z12("EnumerateVars-Assignments$2=2@12", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z12);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z13("EnumerateVars-Assignments$2=2@13", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z13);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z14("EnumerateVars-Assignments$2=2@14", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z14);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z2("EnumerateVars-Assignments$2=2@2", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z2);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z3("EnumerateVars-Assignments$2=2@3", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z3);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z4("EnumerateVars-Assignments$2=2@4", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z4);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z5("EnumerateVars-Assignments$2=2@5", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z5);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z6("EnumerateVars-Assignments$2=2@6", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z6);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z7("EnumerateVars-Assignments$2=2@7", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z7);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z8("EnumerateVars-Assignments$2=2@8", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z8);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A2Z9("EnumerateVars-Assignments$2=2@9", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A2Z9);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3("EnumerateVars-Assignments$2=3", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3Z1("EnumerateVars-Assignments$2=3@1", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3Z1);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3Z2("EnumerateVars-Assignments$2=3@2", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3Z2);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3Z3("EnumerateVars-Assignments$2=3@3", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3Z3);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3Z4("EnumerateVars-Assignments$2=3@4", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3Z4);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3Z5("EnumerateVars-Assignments$2=3@5", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3Z5);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3Z6("EnumerateVars-Assignments$2=3@6", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3Z6);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3Z7("EnumerateVars-Assignments$2=3@7", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3Z7);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A3Z8("EnumerateVars-Assignments$2=3@8", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A3Z8);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4("EnumerateVars-Assignments$2=4", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z1("EnumerateVars-Assignments$2=4@1", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z1);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z10("EnumerateVars-Assignments$2=4@10", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z10);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z11("EnumerateVars-Assignments$2=4@11", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z11);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z12("EnumerateVars-Assignments$2=4@12", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z12);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z13("EnumerateVars-Assignments$2=4@13", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z13);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z14("EnumerateVars-Assignments$2=4@14", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z14);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z2("EnumerateVars-Assignments$2=4@2", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z2);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z3("EnumerateVars-Assignments$2=4@3", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z3);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z4("EnumerateVars-Assignments$2=4@4", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z4);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z5("EnumerateVars-Assignments$2=4@5", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z5);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z6("EnumerateVars-Assignments$2=4@6", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z6);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z7("EnumerateVars-Assignments$2=4@7", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z7);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z8("EnumerateVars-Assignments$2=4@8", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z8);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A4Z9("EnumerateVars-Assignments$2=4@9", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A4Z9);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5("EnumerateVars-Assignments$2=5", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z1("EnumerateVars-Assignments$2=5@1", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z1);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z10("EnumerateVars-Assignments$2=5@10", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z10);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z11("EnumerateVars-Assignments$2=5@11", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z11);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z12("EnumerateVars-Assignments$2=5@12", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z12);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z13("EnumerateVars-Assignments$2=5@13", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z13);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z2("EnumerateVars-Assignments$2=5@2", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z2);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z3("EnumerateVars-Assignments$2=5@3", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z3);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z4("EnumerateVars-Assignments$2=5@4", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z4);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z5("EnumerateVars-Assignments$2=5@5", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z5);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z6("EnumerateVars-Assignments$2=5@6", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z6);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z7("EnumerateVars-Assignments$2=5@7", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z7);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z8("EnumerateVars-Assignments$2=5@8", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z8);
static refalrts::NativeReference nat_ref_gen_EnumerateVarsm_Assignments_S2A5Z9("EnumerateVars-Assignments$2=5@9", COOKIE1_, COOKIE2_, func_gen_EnumerateVarsm_Assignments_S2A5Z9);

@Mazdaywik
Copy link
Member Author

Mazdaywik commented Nov 30, 2020

Эксперимент показал, что если файл rlc-core.exe.cpp разбить на два в позиции 767 488 (до функции func_gen_DoTokenChain_G21B1S9A2Z16, DoTokenChain~21:1$9=2@16), то BCC 5.5.1 компилирует. А если разбить в позиции 768 314 (после упомянутой функции) — не компилирует.

Всего в файле 955 990 строк.

Но корректнее считать не строки, а объём объектного файла:

30.11.2020  09:24         9 338 170 rlc-core-1.exe.obj
30.11.2020  09:24         2 412 342 rlc-core-2.exe.obj
30.11.2020  09:25        11 746 145 rlc-core.exe.obj

Возможно, можно снизить объём файла, сделав некоторые функции рантайма inline-функциями или макросами. Первыми кандидатами на это являются refalrts::update_***-функции — они по сути выполняют одно присваивание. refalrts::reinit_*** выполняют два присваивания.

Вообще, переделывание кодогенератора результатных выражений в стиле Рефала-05 (#196) в этом контексте становится более осмысленным:

          refalrts::alloc_chars(vm, context[124], context[125], "issed \']\'", 9);
          refalrts::alloc_open_bracket(vm, context[126]);
          refalrts::alloc_ident(vm, context[127], identifiers[ident_Brackets]);
          refalrts::alloc_ident(vm, context[128], identifiers[ident_ADTm_Brackets]);
          refalrts::alloc_ident(vm, context[129], identifiers[ident_NoPos]);
          refalrts::alloc_open_bracket(vm, context[130]);
          refalrts::alloc_close_bracket(vm, context[131]);
          refalrts::alloc_close_bracket(vm, context[132]);
          refalrts::update_name(context[4], functions[efunc_gen_DoTokenChain_G21]);
          refalrts::reinit_ident(context[7], identifiers[ident_Extended]);
          refalrts::reinit_ident(context[20], identifiers[ident_Pattern]);
          refalrts::reinit_open_bracket(context[80]);

При генерации результатных выражений в духе #196 контексты для alloc-функций передаваться не будут, ибо они будут заведомо последовательно распределяться. Т.е. в ассемблере, предположительно, будет push/push/call вместо push/push/push/call, что должно заметно сократить объём целевого файла.

Ещё мелкая оптимизация для режима -OR:

            res = refalrts::splice_evar( res, context[126], context[126] ); /**/
            res = refalrts::splice_evar( res, context[113], context[114] );
            res = refalrts::splice_evar( res, context[125], context[125] ); /**/
            res = refalrts::splice_evar( res, context[107], context[108] );
            res = refalrts::splice_evar( res, context[8], context[11] );
            res = refalrts::splice_evar( res, context[124], context[124] ); /**/
            res = refalrts::splice_evar( res, context[16], context[19] );

Видно, что инструкции splice_evar вызываются для одного узла. Можно распознавать эти случаи и вызывать splice_elem. Мелочь, но почему бы нет.

Также можно заменить refalrts::bracket_pointers непосредственным присваиванием link_info. Тоже может сократить объём объектного файла. Ну, потеряется абстракция. Но за 10 лет развития Простого Рефала → Рефала-5λ эта абстракция ни разу не понадобилась.


Объявление refalrts::bracket_pointers inline-функцией увеличило размер объектного файла:

30.11.2020  09:51        11 829 580 rlc-core.exe.obj

Было:

30.11.2020  09:25        11 746 145 rlc-core.exe.obj

Неожиданно. Стало быть, встраивание кода не факт что здесь поможет.

UPD: замена bracket_pointers на присваивание на уровне кодогенератора (не при помощи inline) наоборот незначительно сократила объём объектного файла:

30.11.2020  11:45        11 639 532 rlc-core.exe.obj

        context[19] = 0;
        context[20] = 0;
        context[21] = refalrts::brackets_left( context[19], context[20], context[17], context[18] );
        if( ! context[21] )
          continue;
        refalrts::bracket_pointers(context[21], context[22]);

Обнуление диапазона перед присваиванием ему избыточно. Всё равно эти переменные перезаписываются. Это обнуление тянется ещё с первой версии Простого Рефала, где я ещё не был уверен в корректности и делал это на всякий случай.

@Mazdaywik
Copy link
Member Author

Mazdaywik commented Dec 1, 2020

Предыдущий коммит оптимизировал перенос плитки из одного элемента:

            res = refalrts::splice_elem( res, context[126] );
            res = refalrts::splice_evar( res, context[113], context[114] );
            res = refalrts::splice_elem( res, context[125] );
            res = refalrts::splice_evar( res, context[107], context[108] );
            res = refalrts::splice_evar( res, context[8], context[11] );
            res = refalrts::splice_elem( res, context[124] );
            res = refalrts::splice_evar( res, context[16], context[19] );

И, как ни странно, это помогло!

Размер объектника:

01.12.2020  09:42        11 660 490 rlc-core.exe.obj

Отсюда вывод: нужно развивать алгоритмы кодогенерации (#196, #169, #204).

@Mazdaywik
Copy link
Member Author

Обнаружено очередное зацикливание специализатора на аккумуляторе: #332 (comment).

@Mazdaywik
Copy link
Member Author

Оставался без ответа вопрос: почему компилятор делает так много проходов, нет ли здесь ошибки?

Ответ: это так и должно быть. Число проходов зависит от глубины дерева функций — чем она больше, тем больше проходов. Т.к. оптимизации фактически реализуют ограниченную суперкомпиляцию, то число проходов в принципе непредсказуемо.

Но из общих соображений на каждый «слой» в дереве требуется два прохода прогонки (до неподвижной точки тёплых функций) и проход специализации, в котором появляются новые экземпляры, пригодные для дальнейшей оптимизации. Вот пример:

(s.OptDrive s.OptIntrinsic) e.AST
= (/* no names */) /* no info */ : e.EmptyInfo
= <UpdateDriveInfo s.OptDrive s.OptIntrinsic (e.EmptyInfo) e.AST>;
}

UpdateDriveInfo {
s.OptDrive s.OptIntrinsic ((e.KnownNames) e.KnownFunctions) e.AST
= <ExtractLabels Drive e.AST> : (e.Drives) e.AST^
= <ExtractLabels Inline e.AST> : (e.Inlines) e.AST^
= <ExtractLabels Intrinsic e.AST> : (e.Intrinsics) e.AST^
= <ExtractMetatableNames e.AST> : (e.Metatables) e.AST^
= <SetNames-Reject (e.Drives) (e.Intrinsics)> : e.Drives^
= <SetNames-Reject (e.Inlines) (e.Intrinsics)> : e.Inlines^
= <HashSet-AsChain e.KnownNames> : e.KnownNames^
= <SetNames-Reject (e.Drives) (e.KnownNames)> : e.Drives^
= <SetNames-Reject (e.Inlines) (e.KnownNames)> : e.Inlines^
= <SetNames-Reject (e.Intrinsics) (e.KnownNames)> : e.Intrinsics^
= <SetNames-Reject (e.Metatables) (e.KnownNames)> : e.Metatables^
= <Map
{
(s.Label e.Name)
= '$' <Upper <Explode s.Label>> : e.Label
= <Log-PutLine 'New ' e.Label ' function: ' <DisplayName e.Name>>;
}
e.Drives e.Inlines e.Intrinsics e.Metatables
>
: /* пусто */
= <ExtractBaseNames e.Drives e.Inlines e.Metatables> : e.ExtractedNames
= <ExtractExtractableFunctions (e.ExtractedNames) e.AST>
: (e.Extracted) e.AST^
= <ExtractFuncLengths e.AST> : (e.Lengths) e.AST^
= <MultiplyRemainderNames (e.Lengths) e.Drives> : e.Drives^
= <MultiplyRemainderNames (e.Lengths) e.Inlines> : e.Inlines^

Исходно формируется пустая информация (с пустыми e.KnownNames и e.KnownFunctions), и по этим значениям переменных (на поздних проходах только по e.KnownFunctions) специализируется каждое присваивание. На каждое присваивание уходит три прохода.

Mazdaywik added a commit that referenced this issue Dec 10, 2020
В соответствии с замечанием

#319 (comment)

число проходов увеличено до 300.

Опция -OG пока не включена, т.к. возникают проблемы с компоновкой BCC.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants