Skip to content

javm: thread &mut Cache through EcallHandler so cache-touching host calls work #847

Description

@sorpaas

Background

After the Cap-type consolidation (branch cached-cap, commits 4c0e6f27647982), 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:

  • host_open — needs to publish the resolved DataCap into the cache, set dst slot to the resulting hash
  • host_save — needs to read the DataCap's size from the cache for quota debit; publish the file mapping
  • host_read_data_cap — needs to cache.get(href) and copy bytes into mem
  • host_mint_data_cap — needs to publish a new DataCap from memory bytes
  • host_type_of — needs to read the source cap from the cache to extract image_hash_chain
  • set_image — updates image_hash_chain + image_hash on the entry but does not re-fetch the new image's bytecode from the cache nor re-predecode via image_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 subsequent cache.get(href) fails.

In rust/jar-kernel/src/kernel_assist.rs:

  • SigmaKernelAssist::host_save debits a placeholder 1 byte (no &mut Cache borrow to read the actual data size).

Design options

Two reasonable shapes:

  1. 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 }.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions