diff --git a/hbrt/vm.go b/hbrt/vm.go index 01b32b8..b4ac4dc 100644 --- a/hbrt/vm.go +++ b/hbrt/vm.go @@ -60,6 +60,23 @@ func RegisterDynamicFunc(name string, fn func(*Thread)) { libRegistryMu.Unlock() } +// LibRegistrySnapshotAndDrain returns the registered lib modules and dynamic +// functions and clears the global registry. Use to install the SAME symbol set +// into multiple VMs (a VM pool): snapshot once, then RegisterModule / +// RegisterSymbol into each VM. Modules hold only function pointers + metadata +// (per-VM mutable state — statics/threads/memvars — lives on the VM), so the +// same *Module is safe to share across VMs. Draining prevents VM.Run from +// re-registering libModules into whichever VM happens to run first. +func LibRegistrySnapshotAndDrain() ([]*Module, []Symbol) { + libRegistryMu.Lock() + defer libRegistryMu.Unlock() + mods := libModules + dyns := dynamicFuncs + libModules = nil + dynamicFuncs = nil + return mods, dyns +} + // RegisterLibModules registers any pending lib modules and dynamic functions. func (vm *VM) RegisterLibModules() { libRegistryMu.Lock()