169 похожих чатов

Я тут подумал что wasm с пропозалом GC и всякими

mult-value, reference+function types, exception-handling, stack-switching, etc становится все больше и больше похожим на высокоуровневый язык программирования и пришла идея искуственно ограничить функционал чтобы почувствовать все "удовольствие" от написания компилятора и в итоге получился такой список
1) запрет новых расширений (gc, mult-value, reference+function types, exception-handling, etc)
2) запрет на использование глобальных переменных (global.get, global.set) - вместо этого используем память
3) запрет на использование инструкций if-else - вместо этого используем block + br_if
4) запрет на использование инструкций call/call_indirect/return и функций - вместо этого компилируем всю программу в одну большую main-функцию а наши семантические функции компилируем в набор блоков (вложенный список block block block ..) на которые будет прыжок инструкцией br_table (ну и еще дополнительный loop сверху) ну и также вручную ментейним стек в памяти
5) запрещаем использование стека для построения дерева вычислений - то есть используем стек только для выполнения нативных инструкции (то есть размер стека в любой точки программы должен быть 2 или 1 или 3 в зависимости от количества операндов следующей инструкции) а все промежуточные результаты храним в локальных переменных (то есть постоянно загружаем и наоборот сбрасываем туда результат после выполнения каждой wasm-инструкции)
6) ограничиваем количество локальных переменных примерно 16 штуками ну а поскольку у нас будет одна функция на всю программу и будет запрет на использование глобальных переменных - то это максимальное число переменных где мы можем хранить результат промежуточных вычислений а если нужно больше то используем память (и дальше приходим к идее анализа лайфтайма переменных и запись/чтения из памяти как можно реже)
Что думаете?

14 ответов

72 просмотра

Это всё чтобы «получить удовольствие»?)

Богдан- Автор вопроса
Vladimir Gordeev
Это всё чтобы «получить удовольствие»?)

Не только, можно еще сказать что после того как напишешь wasm-компилятор какого-то языка со всеми этими ограничения то дальше добавления в компилятор кодгена для других процессорных архитектур вроде x64 и Arm будет либо тривиальной либо на порядки более простой задачей чем когда wasm-компилятор разрабатывался бы без этих ограничений

может стоит просто начать, получить хотя бы что-то рабочее, а потом уже двигаться в определенном направлении?

Богдан- Автор вопроса

Кароче, я понял зачем это нужно и всерьез планирую написать wasm-компилятор со всеми этими ограничениями. Все эти ограничения мне нужны для реализации одной киллер-фичи (про которую я не слышал ни в одном языке который компилируется в wasm) - дебаг изнутри браузера. Представьте себе типичную песочницу (например codesandbox.io) где юзеры могут набирать в браузерном редакторе код (например todo-app демки) а справа видят iframe с результатом. Так вот, киллер-фича про которую я не слышал ни в одном wasm-языке (и даже в JS экосистеме) - это возможность дебага внутри этого браузерного веб-редактора не открывая девтулзы (то есть возможность поставить брекпоинт и дальше остановиться на нем и инспектировать локальные переменные, результат временных выражений, память, объекты и т.д) И главное - пока выполнение не дошло до строчки где стоит брейкпоинт то этот код должен выполняться со скоростью оптимизированного бинарника (а то иначе можно представить такой дебаг в браузере который будет работать через интерпретацию кода а это слишком медленно)

Богдан
Кароче, я понял зачем это нужно и всерьез планирую...

.NET так делает. Они просто весь свой рантайм в MVP скомпилировали и получили дебаг из коробки

Богдан- Автор вопроса
Ilya Rezvov
.NET так делает. Они просто весь свой рантайм в MV...

а разве там дебаг не через интерпретацию в виртуальной машине работает?

Богдан
а разве там дебаг не через интерпретацию в виртуал...

Ну да. Я же говорю, они рантайм весь тащат вместе с вм

Богдан- Автор вопроса
Ilya Rezvov
Ну да. Я же говорю, они рантайм весь тащат вместе ...

Тогда это не то. У меня есть идея как это может работать без рантайма и без падения производительности. То есть чтобы дебаг-режим (пока выполнение не дошло до строчки с брекпоинтом) работал со скоростью обычного скомпилированного в wasm кода как в языках С++ и Rust но чтобы дебажить этот код можно было изнутри редактора в браузере без открытия браузерных devtools

Богдан
Тогда это не то. У меня есть идея как это может ра...

Если бы ещё "switch в цикле" работал без падения произволительности, ага... 😏

а как ты собираешься остановить выполнение кода когда он встретит брейкпоинт?

Богдан- Автор вопроса
Alexander Chichigin
Если бы ещё "switch в цикле" работал без падения п...

И насколько это медленее? Есть ли где-то замеры? По сути вместо вызова функции там будет установка константы в локальную переменную и после этого прыжок (например br 123) на заголовок цикл где будет br_table(get_local(0)) и предполагаю что после инлайна этого заголовка и прогона оптимизаций ассемблерный выхлоп в том же x64 сведется к одной и той же инструкции индирект джапа. То есть это медленнее конечно чем прямой джамп но по идее должен быть паритет с инструкцией call_indirect. Более того мне я слышал что есть какие-то оптимизации (вроде jump threading) которые вообще могут проанализировать зависимость пути выполнения по значению из локальной переменной (которое устанавливается в другом блоке) и в итоге раскрутить и заменить косвенный джамп на прямой. В любом случае других альтернатив этому подходу нет - если мы хотим дебажить код изнутри веб-страницы (не открывая девтулзы) то так или иначе придется заменить встроенный wasm-стек на собственный

Богдан
И насколько это медленее? Есть ли где-то замеры? П...

На достаточно медленнее чтобы авторы интерпретаторов всячески пытались ублажить предсказатель переходов и сократить количество итераций цикла (суперинструкции, например).

Богдан- Автор вопроса
cevek
а как ты собираешься остановить выполнение кода ко...

Там будет прыжок на блок который дампит локальные переменные память а после этого делает unreachable или return. Куда более интересный вопрос - как устанавливать брекпоинты и как потом продолжить выполнение

Богдан- Автор вопроса
Alexander Chichigin
На достаточно медленнее чтобы авторы интерпретатор...

Но ведь у меня не интерпретатор. У меня будет обычный wasm код просто со списком этих ограничений - https://t.me/WebAssembly_ru/52284 Там не будет switch-а с каждой строчкой/выражением/оператора как в интерпретаторах. Весь локальный код внутри функции будет выполняться как обычный скомпилировванный в wasm-код а switch-прыжки будут только в случае вызова других функции (но и то есть подозрения что после инлайна хедера цикла и прогона jump-threading оптимизации оверхед от этих прыжков будет минимальным)

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта