Background
After the Cap-type consolidation (branch cached-cap, commits 4c0e6f2 → 7647982), slot values are CapHashOrRef into a Cache<Global> and cap content lives in the cache. Most host calls and some MGMT ops need to read/write the cache mid-interpreter — but EcallHandler::handle(&mut self, kind, regs, mem) doesn't expose the cache because Vm already holds &mut self for the duration of Interpreter::run(..., self). Threading a &mut Cache through would alias.
As an explicit V1 trade-off, the affected operations currently Exit(ExitReason::Trap) from the ecall path. They're inert in tests today because no green path exercises them, but any non-trivial chain bytecode will hit them.
Operations that currently trap
In rust/javm/src/ecall.rs:
In rust/jar-kernel/src/kernel_assist.rs:
Design options
Two reasonable shapes:
- Split Vm. Move the cache borrow out of
Vm and into a per-invocation context (EcallHandler wraps &mut Cache directly). Requires reshaping EcallHandler::handle to accept a context object or splitting Vm into &Vm (immutable view of stack/program) + &mut EcallCtx { cache, kernel_assist }.
- Deferred-effect queue. Each ecall returns an
EcallEffect enum (publish cap, set slot, ...) that the post-Interpreter::run driver applies against the cache. Keeps EcallHandler borrow-free of the cache but introduces a serialization step and requires effects to commute with continued execution (they do for the host_* / mgmt_cnode_mint cases — those exit the interpreter via Continue after the effect lands).
The deferred-effect path is closer to how set_image already wants to work (the program reload needs to interleave with Continue); the split-Vm path is closer to the Nub::invoke_cached shape.
Acceptance
- All operations above stop trapping.
- jar-kernel's
SigmaKernelAssist::host_save debits the real data size.
- A test in
rust/javm/src/ecall.rs per operation exercises the round-trip via cache.get(href) post-call.
Spawned from work on branch cached-cap.
Background
After the Cap-type consolidation (branch
cached-cap, commits 4c0e6f2 → 7647982), slot values areCapHashOrRefinto aCache<Global>and cap content lives in the cache. Most host calls and some MGMT ops need to read/write the cache mid-interpreter — butEcallHandler::handle(&mut self, kind, regs, mem)doesn't expose the cache becauseVmalready holds&mut selffor the duration ofInterpreter::run(..., self). Threading a&mut Cachethrough would alias.As an explicit V1 trade-off, the affected operations currently
Exit(ExitReason::Trap)from the ecall path. They're inert in tests today because no green path exercises them, but any non-trivial chain bytecode will hit them.Operations that currently trap
In
rust/javm/src/ecall.rs:host_open— needs to publish the resolved DataCap into the cache, set dst slot to the resulting hashhost_save— needs to read the DataCap's size from the cache for quota debit; publish the file mappinghost_read_data_cap— needs tocache.get(href)and copy bytes into memhost_mint_data_cap— needs to publish a new DataCap from memory byteshost_type_of— needs to read the source cap from the cache to extractimage_hash_chainset_image— updatesimage_hash_chain+image_hashon the entry but does not re-fetch the new image's bytecode from the cache nor re-predecode viaimage_cache.get_or_decode. Program execution continues on the old predecoded bytecode.mgmt_cnode_mint— stores the new empty cnode's content hash at the dst slot but does not publish the cnode body to the cache, so subsequentcache.get(href)fails.In
rust/jar-kernel/src/kernel_assist.rs:SigmaKernelAssist::host_savedebits a placeholder 1 byte (no&mut Cacheborrow to read the actual data size).Design options
Two reasonable shapes:
Vmand into a per-invocation context (EcallHandlerwraps&mut Cachedirectly). Requires reshapingEcallHandler::handleto accept a context object or splitting Vm into&Vm(immutable view of stack/program) +&mut EcallCtx { cache, kernel_assist }.EcallEffectenum (publish cap, set slot, ...) that the post-Interpreter::rundriver applies against the cache. KeepsEcallHandlerborrow-free of the cache but introduces a serialization step and requires effects to commute with continued execution (they do for the host_* / mgmt_cnode_mint cases — those exit the interpreter viaContinueafter the effect lands).The deferred-effect path is closer to how
set_imagealready wants to work (the program reload needs to interleave withContinue); the split-Vm path is closer to theNub::invoke_cachedshape.Acceptance
SigmaKernelAssist::host_savedebits the real data size.rust/javm/src/ecall.rsper operation exercises the round-trip viacache.get(href)post-call.Spawned from work on branch
cached-cap.