pub struct Vm { /* private fields */ }Expand description
One virtual Flow’s execution state: call stack + registers. Cheap
enough to construct that spawning a Flow is a handful of small heap
allocations, not a native thread/stack (contrast: a std::thread reserves
megabytes of stack whether it uses them or not).
Vm owns no scheduler, mailbox, or thread handle — see VmResult for
why that separation is the whole point.
Implementations§
Source§impl Vm
impl Vm
Sourcepub fn new(
chunk: Arc<Chunk>,
natives: Arc<NativeTable>,
function: u32,
args: &[Value],
) -> Result<Self, Fault>
pub fn new( chunk: Arc<Chunk>, natives: Arc<NativeTable>, function: u32, args: &[Value], ) -> Result<Self, Fault>
Construct a Vm ready to run function (an index into
chunk.functions) with the given arguments loaded into r0..argc.
natives is the FFI table Opcode::CallNative dispatches through —
pass NativeTable::empty if the chunk never calls out to Rust.
pub fn instructions_executed(&self) -> u64
Sourcepub fn current_function(&self) -> u32
pub fn current_function(&self) -> u32
Index into chunk.functions for the active (top) call frame.
Useful for diagnostics / supervisor logs when a Flow traps.
Sourcepub fn chunk_arc(&self) -> Arc<Chunk> ⓘ
pub fn chunk_arc(&self) -> Arc<Chunk> ⓘ
A cheap Arc clone of the chunk this VM is executing. Used by the
scheduler to construct a child Vm for Opcode::Spawn without
needing to know anything about Chunk’s internals — every Flow
spawned (transitively) from the same top-level spawn() call shares
one immutable chunk in memory, never copies it.
Sourcepub fn natives_arc(&self) -> Arc<NativeTable> ⓘ
pub fn natives_arc(&self) -> Arc<NativeTable> ⓘ
A cheap Arc clone of this VM’s native function table, for the same
reason as Vm::chunk_arc: a Spawn-created child must dispatch
CallNative through the identical table its parent uses.
Sourcepub fn resume_with(&mut self, dest_reg: u8, value: Value) -> Result<(), Fault>
pub fn resume_with(&mut self, dest_reg: u8, value: Value) -> Result<(), Fault>
Deliver a value the scheduler produced on our behalf (a Cap from
Spawn / SelfPid, or a dequeued mailbox message from a Receive)
into the register the instruction that suspended us was targeting,
ahead of the next Vm::run call. A no-op is never valid to skip:
calling run without this after a Spawn/Receive result leaves the
destination register holding its previous (stale) value.
Sourcepub fn run(&mut self, budget: u32) -> VmResult
pub fn run(&mut self, budget: u32) -> VmResult
Run at most budget instructions (cooperative-preemption quantum,
design notes §10-11), or until the Flow completes / needs an
effect the scheduler must perform / faults.
Every exit path is captured by VmResult — this function itself
never panics on malformed verified bytecode; faults are returned,
not thrown, so a buggy Flow can’t take a worker thread down.