TGViewer
Библиотека Go-разработчика | Golang Библиотека Go-разработчика | Golang @goproglib · 24.1K subscribers
Post #7130 3.43K
🖇 Новый пакет для поддержки JIT-компиляторов и встроенных VM

В трекере Go появился proposal #78189. Он предлагает добавить стандартный пакет runtime/jit, который позволит Go-рантайму корректно работать с динамически генерируемым кодом.

В чём проблема

Go компилирует код заранее. Стек-анвайндер рантайма устроен так, что знает только о функциях, зарегистрированных в moduledata на этапе линковки.

Если на стеке оказывается счётчик команд из динамически сгенерированного кода — JIT-компилятора, WASM-рантайма или встроенной VM — рантайм падает с фатальной ошибкой:
runtime: unexpected return pc for somefunc called from 0x7f4a12340010
fatal error: unknown caller pc


Это затрагивает любую программу, которая встраивает JIT, например, база данных компилирует SQL в нативный код, хостит WASM, использует FFI с трамплинами или встраивает скриптовые VM вроде Lua.

Единственный обходной путь сегодня — не вызывать Go-функции из динамического кода вообще, либо использовать промежуточные C-фреймы через cgo, что добавляет около 40 наносекунд накладных расходов и требует cgo-тулчейна.

Что предлагают

Новый пакет runtime/jit с минимальным API. Ключевые части:

Region — структура, описывающая регион исполняемой памяти. Содержит колбэки для анвайндинга (Next), описания фреймов в трейсбеке (Describe) и сканирования корней GC (ScanStack).

Три режима анвайндинга:

UnwindStop
— трейсбек обрывается на JIT-фрейме
UnwindSkip — рантайм пропускает пользовательские фреймы и продолжает
UnwindDeclare — пропускает и описывает фреймы в трейсбеке.

handle := jit.Register(jit.Region{
Lo: uintptr(codeStart),
Hi: uintptr(codeEnd),
Unwind: jit.UnwindDeclare,
Next: myUnwindNext,
Describe: myDescribe,
ScanStack: myScanStack,
})
defer handle.Unregister()


Для кооперации со шедулером — функция Preempt(). JIT-код вызывает её в точках безопасности (заголовки циклов, входы в функции) и возвращает управление Go, если шедулер или GC запросили остановку.

Как это работает внутри

Реестр регионов построен на copy-on-write с атомарным свапом указателя. Анвайндер получает доступ к нему без блокировок. Патчи в traceback.go проверяют пользовательские регионы перед тем, как бросить ошибку на неизвестный счётчик команд. GC получает хук в markroot() для вызова ScanStack.

Горутина остаётся в состоянии _Grunning пока выполняется JIT-код — никакого переключения состояний, никакого освобождения. Это принципиальное отличие от cgocall, который обращается с чужим кодом как с чёрным ящиком.

Статус

Proposal открыт в марте 2026 года. Реализация около 500 строк кода, 15 тестов, трамплины для всех 13 Linux-архитектур. Проверена в продакшне в движке базы данных MemCP.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoLive
  • 👍 18
  • ❤ 4
  • 👾 1
More from @goproglib
  1. Sep 30, 2026🧑‍💻 Эмулятор AWS-сервисов Kumo — это небольшой инструмент на Go для локальной имитации A…
  2. Sep 29, 2026👨‍💻 Библиотека для написания LSP-серверов Написать свой Language Server с нуля на Go сло…
  3. Sep 28, 2026🤔 Вопрос с собеседования по Go Что выведет программа? ❤️ — 1 true / 0 false 🔥 — 1 true /…
  4. Sep 28, 2026👩‍💻 Что на самом деле происходит внутри Go map? После Go 1.24 обычный map внутри работае…
  5. Sep 26, 2026🔥 В Go 1.27 появился portable SIMD До этого SIMD-оптимизации в Go требовали архитектурног…
  6. Sep 25, 2026🤡🤡 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека Go-разработчика #GoGiggle
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →