Во-первых, чтобы не показалось, что это проблема XYZ, я хотел бы дать некоторый контекст (заметьте, я не использую Emscripten):
Я пытаюсь выяснить, могу ли я реализовать форму горячая перезагрузка для программ Wasm, написанных на C ++, размещенных в сети. Для этого я хочу иметь раздел памяти, который я называю своим «состоянием мира» (всем, кто смотрел Handmade Hero (https://handmadehero.org/), это будет знакомо):
struct State {
// put everything here
} state;
Обычно для полной программы на C ++ с уровнем платформы вы размещаете эту структуру на стороне платформы и передаете указатель на эту память через указатель на функцию в части кода reloadable / dll / dylib. Перезагружаемый код помещает ВСЕ в эту постоянную память, поэтому, если код необходимо перекомпилировать и перезагрузить, все состояние будет продолжать существовать, поскольку память была выделена в той части программы, которая не была перезагружена. Насколько я могу судить, в Wasm это невозможно. Во-первых, верно ли мое предположение, что я должен использовать WebAssembly.Memory? - или я могу выделить массив uint8 в js и использовать его для моего постоянного состояния отдельно от памяти программы? Если так, это медленнее?
Так что это будет работать до тех пор, пока я не использую динамический c распределитель, такой как WASI, и вместо этого использую pu sh, которым я могу управлять. (Я думаю, это потому, что, предположим, я использую mallo c для получения адресов памяти и перезагрузки - внутреннее состояние mallo c перезагрузится и будет думать, что вся кучная память доступна, когда она недоступна, поэтому будущие выделения могут затормозить предыдущие .) После перезагрузки я могу сначала скопировать структуру во временный буфер на стороне js, перезагрузить, получить расположение памяти структуры из Wasm (я буду требовать, чтобы она существовала), и скопировать сохраненную память из * 1038. * обратно в положение.
Однако, если я использую указатели, это развалится, потому что, если я изменю программу (что является точкой), __data_end
может измениться, что сместит все адреса! Я проверил флаги компоновщика здесь https://lld.llvm.org/WebAssembly.html, чтобы увидеть, что я мог контролировать Я могу указать, что стек идет перед сегментом данных, но куча все равно идет после этого, что приводит к той же проблеме. Я также могу указать, где расположены глобальные данные, но я считаю, что это не сегмент данных, поэтому сегмент данных переменного размера все еще может компенсировать все мои адреса. Вот хорошая страница, которая может помочь нам визуализировать память Wasm: https://dassur.ma/things/c-to-webassembly/
У кого-нибудь есть мысли о том, как достичь того, чего я хочу? Единственные варианты, которые я могу придумать, включают использование памяти вне памяти Wasm (возможно, медленнее или невозможной), использование только стековой памяти и без указателей (нереально c, если только я не могу автоматически пересчитать все смещения указателя после перекомпиляции, что будет болезненный и подверженный ошибкам), или поиск способа заставить сегмент данных следовать за стеком и кучей по фиксированному адресу, что гарантировало бы, что сегменты стека и кучи не будут смещены, если сегмент данных должен расти. Другим вариантом, если это возможно, было бы установить максимальный размер сегмента данных. Спецификация / документация Wasm не очень хороши, когда дело доходит до манипуляций с памятью, поэтому я был бы признателен за разъяснение того, что возможно. Наконец, может быть, я мог бы использовать два модуля Wasm (но разве такого рода косвенность не будет медленной)? Возможно, мне не хватает чего-то важного, связанного с разметкой памяти.
Пожалуйста, дайте мне знать, если вам нужно больше деталей. Как я уже упоминал, я делал что-то подобное в C, и это обычная техника быстрой итерации для разработчиков игр. В основном я пытаюсь воссоздать его в Wasm.
EDIT: Очевидно, вы можете вызывать функции Wasm из другого модуля напрямую. Во-первых, как вы это сделаете, а во-вторых, какими будут характеристики производительности для доступа к памяти другого модуля?
EDIT2: Может быть, какая-то форма динамического c связывания, если это поддерживается? https://webassembly.org/docs/dynamic-linking/