← На главную

Wasmtime 47 добавил Wasm GC и исключения: языки с GC без костылей

20.07.2026 17:10 · hackernews

Wasmtime 47 вышел с включёнными по умолчанию поддержкой Wasm GC и исключений. Это итог нескольких лет инженерной работы, который открывает дорогу гораздо большему числу языков в мир WebAssembly и везде, где запускается Wasmtime.

Раньше языкам с объектно-ссылочной моделью данных приходилось встраивать собственный сборщик мусора прямо внутрь .wasm-бинарников. Получались раздутые файлы, а нормальные техники вроде stack maps и обхода стека для поиска корней GC были недоступны. Предложение Wasm GC снимает эту проблему — теперь Wasm-программа может определять свои типы struct и array, а контроль времени жизни отдаётся рантайму. Например, узел двоичного дерева описывается прямо в коде, новые экземпляры создаются через struct.new, а поля читаются инструкциями вроде struct.get. Никакого ручного освобождения памяти.

Примерно так же устроена и польза от предложения по исключениям. Без него цепочки инструментов придумывали собственные соглашения о вызовах, где каждый вызов проверял, не вернулось ли исключение, добавляя оверхед на нормальном, горячем пути. Теперь же на смену приходят привычные throw и try/catch. Рантайм может реализовать их через классический unwinding с нулевыми накладными расходами на обычных возвратах из функций.

Сборщик мусора в самом Wasmtime сделан по простой схеме Cheney-style semi-space copying. Куча делится на две половины: активный semi-space, куда идёт выделение bump-указателем, и неактивный. При сборке живые объекты копируются из прежнего активного пространства в новое, а все корни GC обновляются. Барьеры чтения или записи не нужны. Самое интересное — GC-куча построена поверх линейных памятей WebAssembly. Ссылки на объекты GC — это не нативные указатели, а 32-битные индексы внутрь этой памяти. Такой подход даёт защиту в глубину: даже при баге сборщика вредоносная Wasm-программа не выберется из песочницы. Быстродействие тоже выигрывает: guard pages на виртуальной памяти убирают лишние проверки границ, 32-битные ссылки плотнее сидят в кешах CPU, а интеграция с аллокатором пулов инстансов позволяет держать время инстанцирования в пределах 5 микросекунд. Портируемость достаётся почти бесплатно, потому что код линейных памятей и так работает на всех платформах.

Чтобы отловить ошибки, разработчики расширили фаззер wasm-smith поддержкой GC и добавили ещё два прицельных фаззера: один гоняет сложные графы объектов и иерархии подтипов, второй выискивает повреждения кучи из-за багов сборщика или неправильной оптимизации в компиляторе. По производительности честно предупреждают: пока главный фокус был на корректности, а не на скорости. Конкурировать с многолетними настройками сборщиков V8 и SpiderMonkey новый код не может. К тому же дефолтный сценарий Wasmtime в продакшене — множество маленьких одноразовых инстансов, которые живут недолго и выкидываются вместе со своей GC-кучей. Систему затачивали под горизонтальное масштабирование на множество инстансов, а не на бесконечно живущий сервер.

Впереди — оптимизации alias-analysis в компиляторе с использованием информации о типах GC, особенно когда известно, что два типа никогда не пересекаются в памяти. Следующий крупный шаг — прототип интеграции GC с компонентной моделью поверх lazy value lowering. Это сделает языки со сборкой мусора полноценными участниками component-экосистемы, и им больше не понадобятся неиспользуемые линейные памяти только для передачи данных. Попробовать всё новое уже можно — берите свежий Wasmtime 47.

Читать оригинал →