Skip to main content

Module runtime

Module runtime 

Source
Expand description

The composed component runtime — the ONLY composition surface embedding applications touch (scaffold-unification design, §5.2, finding B6).

§Why this wrapper exists (the composition story)

Before this module, every embedding host — frame-host’s runtime.rs and every frame new scaffold in the wild — hand-wrote the same five beamr compositions, each of which hides a trap:

  1. Scheduler composition. A bare Scheduler::with_services silently installs an EMPTY built-in-function registry, so every erlang:* import in hot-loaded bytecode resolves Deferred and guard-BIF dispatch kills the process at its first arithmetic instruction with InvalidOperand("guard bif native import") — the composition defect attributed in frame-host/attribution/gcbif-wedge/ (Artemis’s 2026-07-18 probe report, Round 2). ComponentRuntime::compose absorbs the fix, crate::composition::compose_scheduler: gate-1 BIF population BEFORE construction, so load-time import resolution binds erlang:* to Native entries.
  2. Support-module hot load. A component’s FFI bytecode is hot-loaded directly on the scheduler, outside the registry’s lifecycle — and the registry’s deferred-BIF wall did not cover it. ComponentRuntime::load_support_module applies the same wall (the crate-internal composition::deferred_erlang_imports scan both paths share) and returns an opaque SupportModuleHandle instead of a beamr atom.
  3. Support-module unload. The correct teardown is a dance: purge any retained old generation, delete the current one, then VERIFY the module is actually gone. ComponentRuntime::unload_support_module performs and verifies it; the single-use handle makes a double unload unrepresentable.
  4. Mailbox acknowledgement values. BEAM mailbox integers must fit the small-integer term payload, and the low integers are usually claimed by a child’s message protocol (liveness, stop). Deriving an acknowledgement from identifier bytes therefore means folding into reserved_below ..= Term::SMALL_INT_MAX — previously hand-rolled against Term::SMALL_INT_MAX in generated code, now mailbox_integer.
  5. Teardown discipline. Scheduler::shutdown is not cleanup: ordered stop must have drained every process tree first. ComponentRuntime::shutdown refuses while ComponentRuntime::live_process_count is nonzero.

Zero beamr types appear in this module’s public signatures: bytecode is &[u8], modules are opaque handles, mailbox messages are the i64 the registry already speaks. The runtime’s beamr dependency (and its feature selection) is therefore declared in exactly one place — frame-core’s own manifest — instead of being fossilized into every generated application (finding B6). crate::composition remains public as the wrapper’s ground truth for embedders that need raw scheduler access; applications and frame-host itself compose only through this module.

Structs§

ComponentRuntime
The composed component runtime: scheduler + registry, correctly assembled.
RuntimePolicy
Stated-by-the-application runtime policy. No field has a default: frame supplies no lifecycle values, so the embedding application declares each one explicitly.
SupportModuleHandle
Opaque, single-use handle to a loaded support module.
SupportModuleRef
A cloneable reference to a loaded support module’s NAME, for hot swaps. Carries no unload authority.
SupportSwapper
A Send + Sync handle for hot-swapping support modules from the management adapter’s thread (the F-7b dev reload’s FFI leg).

Enums§

RuntimeError
A typed refusal or failure from crate::runtime::ComponentRuntime or crate::runtime::mailbox_integer.

Functions§

mailbox_integer
Folds identifier bytes into a valid mailbox integer above a reserved range.